如何更新sql server中的前100条记录


393

我想更新SQL Server中的前100条记录。我有一张桌子,上面T1有字段F1F2T1有200条记录。我想更新F1前100条记录中的字段。如何TOP 100在SQL Server中基于更新?

Answers:


684

请注意,括号是UPDATE语句所必需的:

update top (100) table1 set field1 = 1

28
知道如何使用order by
Joe Phillips

8
@JoePhilllips使用马丁史密斯答案进行排序
jjxtra 2014年

这些不是前100条记录,而只是100条任意选择的记录。前100名将包括一些对记录进行排名的顺序。
Thorsten Kettner

1
这回答了“按要求”的问题,但是没有一些ORDER,TOP是毫无意义的(而且是不可预测的)。进一步了解马丁·史密斯的答案。
安迪G

1
顺便说一句:括号很重要!
Simon_Weaver

300

没有一个ORDER BY整体的想法是TOP没有任何意义的。您需要对哪个方向是“向上”和哪个“向下”具有一致的定义,以使顶部的概念有意义。

但是,SQL Server允许这样,但不能保证确定的结果

UPDATE TOP接受的答案中的语法不支持ORDER BY子句,但可以在此处通过使用CTE或派生表来定义所需的排序顺序,从而获得确定性语义。

;WITH CTE AS 
( 
SELECT TOP 100 * 
FROM T1 
ORDER BY F2 
) 
UPDATE CTE SET F1='foo'

71
您说的毫无意义,但这不是事实。我承认,通常,当您使用TOP赔率时,应该与之配合使用,ORDER BY因为您感兴趣的东西就像某物的“最”或“最少”。但是,在其他情况下,您可能只对获取一条匹配记录感兴趣。今天喜欢我!我需要一次解决一个数据问题(周期)。整个修复过程涉及数据库脚本,一些用户干预和一些应用程序操作。我们不在乎先处理哪个记录。我们只是关心我们一次要处理它们。
MetaFight 2012年

17
@MetaFight但是,您将拥有一个WHERE子句以排除先前处理的记录。这个问题作为书面答案和公认的答案是毫无意义的。顺便说一句:对于将表用作队列,这是一个非常有用的链接
Martin Smith

10
我需要不按顺序使用top,以便可以运行异步过程。where子句将不包含已经处理过的子句,但是一次只能处理那么多子句。因此,它具有完全有效的用例。
杰夫·戴维斯

4
@马丁史密斯:假设您要分批更新,一次更新10000。似乎是一个很好的用法,顺序无关紧要。这怎么“没有道理”?
杰伊·沙利文

5
@notfed这与上面的评论中已经讨论过的情况相同。在这种情况下,您的查询看起来不会像已接受的答案中的查询吗?您将需要一个where子句来避免一次又一次地处理相同的行。
马丁·史密斯

14

对于像我这样仍然停留在SQL Server 2000中的用户,SET ROWCOUNT {number};可以在UPDATE查询之前使用

SET ROWCOUNT 100;
UPDATE Table SET ..;
SET ROWCOUNT 0;

将更新限制为100行

至少自SQL 2005起已弃用,但自SQL 2017起仍然有效。 https://docs.microsoft.com/zh-cn/sql/t-sql/statements/set-rowcount-transact-sql?view=sql-server-2017


1
SET ROWCOUNT会影响触发器以及要更新的命令。如果您设置了级联删除,则如果子表中存在的子行数超过行数,则事务可能会失败。
艾瑞克(EricI)

这样说,SET ROWCOUNT @RowCountParameter; 是有效的语法,而SELECT TOP @RowCountParamter * FROM TableName无效。如果您需要配置要更新的行,则如果没有启用了级联删除的子表,则SET ROWCOUNT#是当前更好的选择。
艾瑞克(EricI)

在SQL Server 2017年,现在有可能在TOP子句中使用@Variable:docs.microsoft.com/en-us/sql/t-sql/queries/...
亚历山大Zarubkin

13
update tb set  f1=1 where id in (select top 100 id from tb where f1=0)

4

更酷的是,您可以使用内联表值函数来选择TOP要更新的行(以及多少行)。那是:

UPDATE MyTable
SET Column1=@Value1
FROM tvfSelectLatestRowOfMyTableMatchingCriteria(@Param1,@Param2,@Param3)

对于表值函数,您有一些有趣的事情来选择要更新的行,例如:

CREATE FUNCTION tvfSelectLatestRowOfMyTableMatchingCriteria
(
    @Param1 INT,
    @Param2 INT,
    @Param3 INT
)
RETURNS TABLE AS RETURN
(
    SELECT TOP(1) MyTable.*
    FROM MyTable
    JOIN MyOtherTable
      ON ...
    JOIN WhoKnowsWhatElse
      ON ...
    WHERE MyTable.SomeColumn=@Param1 AND ...
    ORDER BY MyTable.SomeDate DESC
)

...,而且(以我的拙见)存在确定性地仅更新前几行的真正力量,同时简化了UPDATE语句的语法。


0

尝试:

UPDATE Dispatch_Post
SET isSync = 1
WHERE ChallanNo 
IN (SELECT TOP 1000 ChallanNo FROM dbo.Dispatch_Post ORDER BY 
CreatedDate DESC)

0

您也可以使用别名和联接从select更新:

UPDATE  TOP (500) T
SET     T.SomeColumn = 'Value'
FROM    SomeTable T
        INNER JOIN OtherTable O ON O.OtherTableFK = T.SomeTablePK
WHERE   T.SomeOtherColumn = 1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.