Ответ 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
Можно ли добавить TOP или какой-то пейджинг в инструкцию SQL Update?
У меня есть запрос UPDATE
, который сводится к следующему:
UPDATE XXX SET XXX.YYY = #TempTable.ZZZ
FROM XXX
INNER JOIN (SELECT SomeFields ... ) #TempTable ON XXX.SomeId=#TempTable.SomeId
WHERE SomeConditions
Это обновление повлияет на миллионы записей, и мне нужно делать это партиями. Как и 100 000 в то время (заказ не имеет значения)
Каков самый простой способ сделать это?
Да, я считаю, что вы можете использовать TOP в операторе обновления, например:
UPDATE TOP (10000) XXX SET XXX.YYY = #TempTable.ZZZ
FROM XXX
INNER JOIN (SELECT SomeFields ... ) #TempTable ON XXX.SomeId=#TempTable.SomeId
WHERE SomeConditions
Вы можете использовать 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
отключить ограничения - не забывайте об этом.
В зависимости от вашей способности изменять структуру данных таблицы, я бы предположил, что вы добавляете поле в свою таблицу, которое может содержать какой-то пакетный идентификатор. То есть. это может быть отметка даты, если вы делаете это ежедневно, добавочное значение или в основном любое значение, которое вы можете сделать уникальным для своей партии. Если вы примете инкрементный подход, ваше обновление будет следующим:
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 и уменьшить нагрузку на сервер.
Вы можете сделать что-то вроде следующего
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