如何批量执行SQL UPDATE,如Update Top?

时间:2012-01-11 14:01:34

标签: sql sql-server-2008 tsql

是否可以在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(排序无关紧要)

最简单的方法是什么?

5 个答案:

答案 0 :(得分:19)

是的,我相信您可以在更新声明中使用TOP,如下所示:

UPDATE TOP (10000) XXX SET XXX.YYY = #TempTable.ZZZ
FROM XXX
INNER JOIN (SELECT SomeFields ... ) #TempTable ON XXX.SomeId=#TempTable.SomeId
WHERE SomeConditions

答案 1 :(得分:5)

您可以使用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

我已将XXX.YYY <> #TempTable.ZZZ添加到where子句,以确保您不会更新两次已更新的值。

ROWCOUNT设为0 关闭限制 - 不要忘记

答案 2 :(得分: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

答案 3 :(得分:3)

根据您更改表格数据结构的能力,我建议您在表格中添加一个可以容纳某种批次标识符的字段。 IE浏览器。如果你每天都这样做,它可以是一个日期戳,一个增量值或基本上你可以为你的批次制作的任何值。如果采用增量方法,则更新将为:

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上设置索引并减少服务器上的负载。

答案 4 :(得分:0)

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