2012-01-11 9 views
17

TOPまたは何らかの種類のページングをSQL Updateステートメントに追加できますか?更新トップのようなバッチで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と同じです(注文は関係ありません)

これを行う最も簡単な方法は何ですか?

答えて

17

はい、私はあなたがそうのように、更新ステートメントでTOPを使用することができると信じて:

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'ような何かを行うことができますか?第2のバッチは、最初のバッチがどこで終わったのですか? –

+0

1つの可能性は、更新されるごとに各レコードにフラグを立て、既に更新されたレコードを無視して別の節を追加することです。これは一時的にテーブルに列を追加する必要があります(レコードが更新自体によって更新されたかどうかを確認する効率的な方法がない限り) – ean5533

+0

これは簡単なことです。UPDATE TOP 100000でテストしましたが、 '100000に近い不正な構文 '、TOP(100000)の更新が動作するようです。 @MartinSmith:私の場合、「第2のバッチ」は重要ではありません。最初のバッチが更新されると、それはwhere条件にもう一致しません。 –

3

テーブルのデータ構造を変更するには、あなたの能力に応じて、私はあなたがあなたのテーブルにフィールドを追加することを示唆していますバッチ識別器のようなものを保持することができます。つまり毎日行う場合は日付スタンプ、増分値、または基本的にはバッチに固有の任意の値にすることができます。あなたはインクリメンタルなアプローチを取る場合は、あなたの更新はその後、次のようになります。

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に追加し、サーバーの負荷を軽減します。

5

あなたは以下の例では、それが特定のクエリを停止する前に処理された行の数を制限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.ZZZwhereに句を追加しました。

設定をROWCOUNTから0に設定することを忘れないでください。を忘れないでください。

+0

また、良いと働く答えが、私は1つだけを受け入れることができます。もう一つの答えは、私が望むことをやるための最短かつ最速の方法です。 –

+2

SET ROWCOUNTは、UPDATE、INSERTおよびDELETEステートメントを制限するために推奨されていません。 SQL 2005以降では、TOPを使うべきです。上記の – Jim

+0

のコメントは役に立ちます。ここでそれをサポートしています:https://sqlstudies.com/2013/10/07/use-top-instead-of-set-rowcount/ – jacoblambert

2

何で順序付けられたあなたは、次の

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 
関連する問題