2016-10-03 4 views
1

1回のトランザクションで10kレコードの制限を入れるために、SQL Serverのテーブルを更新する最も効果的な方法は何ですか?バッチ内でのSqlの更新

私はトップを読んで、ROWCOUNTアプローチをwhileループで追加しています。そのうちどちらが効果的ですか?あるいは、別の効果的な方法を知っている場合は、共有してください。ありがとうございました。ここで

+0

現時点ではどのスクリプトを使用していますか? – mfredy

+0

ROWCOUNTを使用して、UPDATE文で行を更新する方法を制御しないでください。これに対する使用は廃止され、将来的には機能しなくなります。 https://msdn.microsoft.com/en-us/library/ms188774.aspx –

+0

一度に10,000行ごと、または一番上の10,000行だけを更新する予定ですか? – ZLK

答えて

0

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

を使用せずに1個の潜在的なアプローチは、あなたが以下のアプローチを試すことができます:組織と作りの全従業員のための

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

更新それが完全なループにならないことを確かめてください。ここでは、従業員レコードのmodifiedDateを更新しています。

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

同じ10000行が連続的に更新される可能性があるため、デッドループになります。 (私がテストしたSQLサーバでは少なくとも) – jyao

+0

WHERE句が見つかりませんでした。ごめんなさい。私はコードを更新しました。私は主にロジックに集中しました。 –

+0

テーブルのGENERIC更新では、既に更新された条件を除外するための有効な条件が存在しないことがあります。たとえば、[emploee_id]と[salary]という2つの列を持つ表があり、すべての人に10%の増加をさせたいとしましょう。この表に100万行があると仮定すると、私たちはこのテーブルを10K /チャンクアップデートで更新したいのですが、どうすればよいwhere節を思いつくことができますか? – jyao