提问人:Erik Dekker 提问时间:1/11/2012 更新时间:9/3/2020 访问量:59605
如何批量执行 SQL UPDATE,例如 Update Top?
How can I do a SQL UPDATE in batches, like an Update Top?
问:
是否可以向 SQL Update 语句添加 TOP 或某种分页?
我有一个查询,可以归结为这样:UPDATE
UPDATE XXX SET XXX.YYY = #TempTable.ZZZ
FROM XXX
INNER JOIN (SELECT SomeFields ... ) #TempTable ON XXX.SomeId=#TempTable.SomeId
WHERE SomeConditions
这次更新会影响数百万条记录,我需要分批进行。就像当时的 100.000 一样(排序无关紧要)
最简单的方法是什么?
答:
23赞
Eric Petroelje
1/11/2012
#1
是的,我相信您可以在更新语句中使用 TOP,如下所示:
UPDATE TOP (10000) XXX SET XXX.YYY = #TempTable.ZZZ
FROM XXX
INNER JOIN (SELECT SomeFields ... ) #TempTable ON XXX.SomeId=#TempTable.SomeId
WHERE SomeConditions
评论
10赞
Martin Smith
1/11/2012
TOP
按照什么命令?第二批如何从第一批完成的地方开始?
0赞
ean5533
1/11/2012
一种可能性是在更新时标记每条记录,然后添加另一个子句,忽略已更新的记录。这需要临时向表中添加一列(除非有一些有效的方法来判断记录是否已通过更新本身进行更新)
0赞
Erik Dekker
1/11/2012
呃,这很简单..我用 UPDATE TOP 100000 进行了测试,但这给出了一个 ,Update TOP (100000) 似乎有效。@MartinSmith:“第二批”在我的情况下并不重要。当第一批更新时,它将不再与 where 条件匹配。Incorrect syntax near 100000
5赞
Eric Petroelje
1/11/2012
@Martin - 运算符不需要 ,因此大概是按聚簇索引顺序排列的。至于让第二批从第一批中断的地方继续,您需要在子句中添加一些内容来过滤掉已经更新的记录。很难确切地说那会是什么样子,但如果不知道有关他的查询的更多信息。TOP
ORDER BY
WHERE
1赞
Eric Petroelje
1/11/2012
@Erik - 是的,奇怪的是,在更新中使用时需要括号(但在选择中不需要..)TOP
3赞
user806549
1/11/2012
#2
根据您更改表数据结构的能力,我建议您在表中添加一个可以容纳某种批处理标识器的字段。即。如果您每天这样做,它可以是日期戳、增加值或基本上可以为您的批次设置唯一的任何值。如果采用增量方法,则更新将为:
UPDATE TOP (100000) XXX SET XXX.BATCHID = 1, XXX.YYY = ....
...
WHERE XXX.BATCHID < 1
AND (rest of WHERE-clause here).
下次,您将设置 BATCHID = 2 和WHERE XXX.BATCHID < 2
如果要重复执行此操作,则可以在 BATCHID 上设置索引并减少服务器上的负载。
5赞
Michał Powaga
1/11/2012
#3
您可以使用 SET ROWCOUNT { number | @number_var }
来限制在停止特定查询之前处理的行数,示例如下:
SET ROWCOUNT 10000 -- define maximum updated rows at once
UPDATE XXX SET
XXX.YYY = #TempTable.ZZZ
FROM XXX
INNER JOIN (SELECT SomeFields ... ) #TempTable ON XXX.SomeId = #TempTable.SomeId
WHERE XXX.YYY <> #TempTable.ZZZ and OtherConditions
-- don't forget about bellow
-- after everything is updated
SET ROWCOUNT 0
我已添加 to 子句,以确保您不会更新已更新的值两次。XXX.YYY <> #TempTable.ZZZ
where
设置为关闭限制 - 不要忘记它。ROWCOUNT
0
评论
0赞
Erik Dekker
1/12/2012
也是一个很好的有效答案,但我只能接受一个。另一个答案是做我想做的事的最短和最快的方法。
2赞
Jim
7/11/2013
不推荐使用 SET ROWCOUNT 来限制 UPDATE、INSERT 和 DELETE 语句。从 SQL 2005 开始,应该使用 TOP。
0赞
jacoblambert
10/5/2016
以上评论是有帮助的;以下是对此的一些支持: sqlstudies.com/2013/10/07/use-top-instead-of-set-rowcount
4赞
W. Nema
8/26/2016
#4
您可以执行如下操作
declare @i int = 1
while @i <= 10 begin
UPDATE top (10) percent
masterTable set colToUpdate = lt.valCol
from masterTable as mt
inner join lookupTable as lt
on mt.colKey = lt.colKey
where colToUpdate is null
print @i
set @i += 1
end
--one final update without TOP (assuming lookupTable.valCol is mostly not null)
UPDATE --top (10) percent
masterTable set colToUpdate = lt.valCol
from masterTable as mt
inner join lookupTable as lt
on mt.colKey = lt.colKey
where colToUpdate is null
1赞
Ani
9/3/2020
#5
DECLARE @updated_Rows INT;
SET @updated_Rows = 1;
WHILE (@updated_Rows > 0)
BEGIN
UPDATE top(10000) XXX SET XXX.YYY = #TempTable.ZZZ FROM XXX
INNER JOIN #TempTable ON XXX.SomeId=#TempTable.SomeId
WHERE SomeConditions
SET @updated_Rows = @@ROWCOUNT;
END
评论