2016-10-03 6 views
1

Was ist der effektivste Weg, um eine Tabelle in SQL Server zu aktualisieren, um eine Grenze von 10k Datensätze in einer einzigen Transaktion zu setzen?SQL-Update in Batches

Ich lese über Top und ROWCOUNT Ansatz, indem Sie es in einer While-Schleife hinzufügen. Was ist unter diesen effektiver? Oder teilen Sie es bitte, wenn Sie alternative effektive Wege kennen. Vielen Dank. Hier

+0

Welches Skript verwenden Sie im Moment? – mfredy

+0

Verwenden Sie ROWCOUNT NICHT, um zu steuern, wie Zeilen mit einer UPDATE-Anweisung aktualisiert werden. Die Verwendung hierfür ist veraltet und wird in Zukunft nicht mehr funktionieren. https://msdn.microsoft.com/en-us/library/ms188774.aspx –

+0

Ist Ihre Absicht, jede Zeile 10.000 auf einmal oder nur die oberen 10.000 Zeilen zu aktualisieren? – ZLK

Antwort

0

ist ein möglicher Ansatz ohne set rowcount

-- prepare test data 
use tempdb 
drop table dbo.t; 
create table dbo.t (a int identity, b int) 
go 
insert into dbo.t (b) 
values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11); 
go 

-- assume we do 3 records per time, put 10000 here if you wnat 10K records 
-- also the update is just to update column [b] to [b] * 2, here is the code 

declare @N int = 3; -- do a batch of @N records 

declare @i int = 0, @max_loop int; 

select @max_loop = count(*)/@N from dbo.t 

-- the first batch may include records <= @N-1 and the last batch may include records <= @N 
while (@i <= @max_loop) 
begin 

    ; with c as (
    select rnk=ROW_NUMBER() over (order by a)/@N, a, b from dbo.t 
    ) 
    update c set b = b*2 -- doule b 
    where rnk = @i; 

    set @i = @i + 1; 
end 
go 
-- check the result 
select * from dbo.t 
-1

Sie können mit dem folgenden Ansatz versuchen:

WHILE (1=1) 
BEGIN 
    BEGIN TRANSACTION 
    UPDATE TOP (10000) XXX 
    SET XXX.YYY = <ValueToUpdate> 
    FROM XXX -- Update 10000 nonupdated rows 
    WHERE <condition> -- make sure that condition makes sure that it does not become infinite loop 
    IF @@ROWCOUNT = 0 
    BEGIN 
     COMMIT TRANSACTION 
     BREAK 
    END 
    COMMIT TRANSACTION 
END 

EDIT

Update für alle Mitarbeiter einer Organisation und Herstellung sicher, dass es nicht zu einer unendlichen Schleife wird. Hier aktualisiere ich modifiedDate für einen Mitarbeiterdatensatz.

DECLARE @updatedids table(id int) 
WHILE (1=1) 
BEGIN 
    BEGIN TRANSACTION 
    UPDATE TOP(10000) a  
    SET a.ModifiedDate = GETDATE() 
    OUTPUT inserted.BusinessEntityID INTO @updatedids 
    FROM HumanResources.Employee a 
LEFT JOIN @updatedids u 
    ON a.BusinessEntityID = u.id 
    WHERE u.id IS NULL 
    -- Update 10000 nonupdated rows 
    IF @@ROWCOUNT = 0 
    BEGIN 
     COMMIT TRANSACTION 
     BREAK 
    END 
    COMMIT TRANSACTION 
END 
+0

Es wird ein Dead Loop sein, da dieselben 10000 Zeilen fortlaufend aktualisiert werden können. (Zumindest in SQL-Server, die ich getestet habe) – jyao

+0

Ich verpasste WHERE-Klausel. Es tut uns leid. Ich habe den Code aktualisiert. Ich habe mich hauptsächlich auf Logik konzentriert. –

+0

Bei einem GENERIC-Update für eine Tabelle existiert manchmal möglicherweise keine gültige Bedingung für das Herausfiltern der bereits aktualisierten. Nehmen wir zum Beispiel an, wir haben eine Tabelle mit zwei Spalten, [emploee_id] und [salary], sagen wir mal, jetzt wollen wir allen Leuten eine 10% ige Erhöhung geben, und wenn wir annehmen, dass diese Tabelle jetzt 1 Million Zeilen hat, Wir wollen diese Tabelle in 10K/Chunk-Update aktualisieren, wie können wir mit einer guten Where-Klausel kommen? – jyao

Verwandte Themen