Как я могу сделать SQL ОБНОВЛЕНИЕ в пакетах, как обновление сверху? - PullRequest
18 голосов
/ 11 января 2012

Можно ли добавить 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 в то время (порядок не имеет значения)

Какой самый простой способ сделать это?

Ответы [ 4 ]

20 голосов
/ 11 января 2012

Да, я полагаю, что вы можете использовать TOP в выражении обновления, например:

UPDATE TOP (10000) XXX SET XXX.YYY = #TempTable.ZZZ
FROM XXX
INNER JOIN (SELECT SomeFields ... ) #TempTable ON XXX.SomeId=#TempTable.SomeId
WHERE SomeConditions
5 голосов
/ 11 января 2012

Вы можете использовать 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 отключение ограничений - не забывайте об этом .

4 голосов
/ 26 августа 2016

Вы можете сделать что-то вроде следующего

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 голосов
/ 11 января 2012

В зависимости от вашей способности изменять структуру данных таблицы, я бы предложил добавить в вашу таблицу поле, которое может содержать какой-то идентификатор партии. То есть. это может быть отметка даты, если вы делаете это ежедневно, добавочное значение или, в основном, любое значение, которое вы можете сделать уникальным для вашей партии. Если вы используете инкрементальный подход, ваше обновление будет:

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 и уменьшить нагрузку на сервер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...