2012-01-11 6 views
17

È possibile aggiungere un TOP o una sorta di paging a un'istruzione SQL Update?Come posso eseguire un UPDATE SQL in lotti, come un aggiornamento superiore?

Ho un UPDATE di query, che si riduce a qualcosa di simile:

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

Questo aggiornamento interesserà milioni di dischi, e ho bisogno di farlo in lotti. Come 100.000 alla volta (l'ordine non importa)

Qual è il modo più semplice per farlo?

risposta

17

Sì, io credo che si possa utilizzare TOP in un'istruzione di aggiornamento, in questo modo:

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

'top' come ordinato da che cosa? Come si riprende il secondo lotto dove finisce il primo? –

+0

Una possibilità sarebbe quella di contrassegnare ogni record man mano che viene aggiornato, quindi aggiungere un'altra clausola ignorando i record che sono già stati aggiornati. Ciò richiederebbe l'aggiunta temporanea di una colonna alla tabella (a meno che non vi sia un modo efficace per stabilire se un record è stato aggiornato in virtù dell'aggiornamento stesso) – ean5533

+0

Eh oke è stato semplice .. Ho provato con UPDATE TOP 100000, ma ciò dà una 'Sintassi errata vicino a 100000', l'aggiornamento TOP (100000) sembra funzionare. @ MartinSmith: Il "secondo lotto" non ha importanza nel mio caso. Quando il primo batch viene aggiornato, non corrisponderà più alla condizione where. –

3

A seconda della capacità di cambiare il datastructure del tavolo, vorrei suggerire che si aggiunge un campo al vostro tavolo che può contenere una sorta di identificatore di batch. Vale a dire. può essere una data-timbro se lo fai ogni giorno, un valore incremen- nale o sostanzialmente qualsiasi valore che puoi rendere unico per il tuo lotto. Se si prende l'approccio incrementale, l'aggiornamento sarà quindi:

UPDATE TOP (100000) XXX SET XXX.BATCHID = 1, XXX.YYY = .... 
... 
WHERE XXX.BATCHID < 1 
    AND (rest of WHERE-clause here). 

La prossima volta, potrai impostare la BatchID = 2 e WHERE XXX.BATCHID < 2

Se questo deve essere fatto più volte, è possibile impostare un indice sul BATCHID e ridurre il carico sul server.

5

È possibile utilizzare SET ROWCOUNT { number | @number_var } limita il numero di righe elaborate prima di interrompere la query specifica, esempio qui sotto:

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 

Ho aggiunto XXX.YYY <> #TempTable.ZZZ-where clausola per assicurarsi che non si aggiorna il valore già due volte aggiornato.

Impostazione ROWCOUNT a 0disattivare i limiti - non dimenticarlo.

+0

Anche una risposta valida e funzionante, ma posso accettarne solo una. L'altra risposta è il modo più breve e veloce per fare ciò che voglio. –

+2

SET ROWCOUNT è deprecato per la limitazione delle istruzioni UPDATE, INSERT e DELETE. Da SQL 2005 in poi, si dovrebbe usare TOP. – Jim

+0

sopra il commento è utile; ecco un supporto per questo: https://sqlstudies.com/2013/10/07/use-top-instead-of-set-rowcount/ – jacoblambert

2

Si può fare qualcosa di simile al seguente

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 
Problemi correlati