2012-02-23 6 views
6

SQL経由で複数の行を効率的に更新する方法について質問があります。C#、SQL複数行の更新

Basiclly私は別のROWIDの実行に必要なクエリを持っている:

UPDATE TableName SET Column = (some number) WHERE RowID = (some number) 

より具体的にあれば、これは、より良い例です。

UPDATE TableName SET Column = 5 WHERE RowID = 1000 
UPDATE TableName SET Column = 10 WHERE RowID = 1001 
UPDATE TableName SET Column = 30 WHERE RowID = 1002 
.. 

私がすべき方法を知りたいのですが私はC#でupdate queryコマンドをビルドします(または、私が得るべき結果クエリの例を与えます).ExputeQueryを使用すると、これらのコマンドはすべて1つのコマンドで実行され、各コマンドは実行されません。編集した

私は別の問題を持って、あなたはまた、私は更新したい行をnecessarlyない動的な状況についているかを説明することができ、その場合には、私は更新の代わりに挿入する必要があり、既に存在しています。良く説明すること、戻って私の例には、行が存在する場合、私はので、私はアップデートを使用したい場合はそうでない私は挿入する必要があります、チェックする必要があるということです私は

UPDATE TableName SET Column = 5 WHERE RowID = 1000 
INSERT INTO TableName [RowID, Column] VALUES (1001, 20) 
UPDATE TableName SET Column = 30 WHERE RowID = 1002 
.. 

これの意味をやりたいと言うことができますそれ。

ありがとうございました!

+0

ストアドプロシージャ? – Vedran

+0

ご使用のデータベース製品とバージョンを確認できますか?最新のSQL Server(> = 2008)では、テーブル値のパラメータとMERGEステートメントを使用しています。 –

答えて

7

あなたは(0は無制限を意味)、あなたのレコードを格納挿入、削除、または変更する行をし、SqlDataAdapterオブジェクトのUpdateBatchSizeを使用して、1つのバッチ内のすべての変更を更新しDataTableを使用することができます。

public static void BatchUpdate(DataTable dataTable,Int32 batchSize) 
{ 
    // Assumes GetConnectionString() returns a valid connection string. 
    string connectionString = GetConnectionString(); 

    // Connect to the AdventureWorks database. 
    using (SqlConnection connection = new 
     SqlConnection(connectionString)) 
    { 

     // Create a SqlDataAdapter. 
     SqlDataAdapter adapter = new SqlDataAdapter(); 

     // Set the UPDATE command and parameters. 
     adapter.UpdateCommand = new SqlCommand(
      "UPDATE Production.ProductCategory SET " 
      + "[email protected] WHERE [email protected];", 
      connection); 
     adapter.UpdateCommand.Parameters.Add("@Name", 
      SqlDbType.NVarChar, 50, "Name"); 
     adapter.UpdateCommand.Parameters.Add("@ProdCatID", 
      SqlDbType.Int, 4, "ProductCategoryID"); 
     adapter.UpdateCommand.UpdatedRowSource = UpdateRowSource.None; 

     // Set the INSERT command and parameter. 
     adapter.InsertCommand = new SqlCommand(
      "INSERT INTO Production.ProductCategory (Name) VALUES (@Name);", 
      connection); 
     adapter.InsertCommand.Parameters.Add("@Name", 
      SqlDbType.NVarChar, 50, "Name"); 
     adapter.InsertCommand.UpdatedRowSource = UpdateRowSource.None; 

     // Set the DELETE command and parameter. 
     adapter.DeleteCommand = new SqlCommand(
      "DELETE FROM Production.ProductCategory " 
      + "WHERE ProductCateg[email protected];", connection); 
     adapter.DeleteCommand.Parameters.Add("@ProdCatID", 
      SqlDbType.Int, 4, "ProductCategoryID"); 
     adapter.DeleteCommand.UpdatedRowSource = UpdateRowSource.None; 

     // Set the batch size. 
     adapter.UpdateBatchSize = batchSize; 

     // Execute the update. 
     adapter.Update(dataTable); 
    } 
} 

http://msdn.microsoft.com/en-us/library/aadf8fk2.aspx

dbmsが内部的にどのように動作するかを誤解していると思います。この

UPDATE TableName SET Column = 5 WHERE RowID = 1000; 
UPDATE TableName SET Column = 5 WHERE RowID = 1002; 

DBMSを使用すると、テーブル内のすべてのレコードに影響を与えるUPDATE table SET value=1のような文を記述した場合でも、とにかくすべての影響を受けるレコードを一つずつ更新します

UPDATE TableName SET Column = 5 WHERE RowID IN(1000,2002); 

と同じです。 1回のバッチで更新することにより、すべての更新(削除、挿入)がすべてのステートメントに対して1回のラウンドトリップではなくデータベースに送信されるようにします。

+0

私は更新コードを表示しています(これは私の質問と最も関連があります)。最後に結果として得られたクエリは何かをよく理解していますが、なぜ効率的ですか?それは避けようとしているあなたのクエリーを構築しているようなものですか? – Popokoko

+1

dbmsは、テーブル内のすべてのレコードに影響を及ぼす「UPDATE table SET value = 1」のような文を書いても、影響を受けたすべてのレコードを1つずつ更新します。1回のバッチで更新することで、すべての更新(削除、挿入)が同じトランザクションで同時にコミットされることを保証します。 –

+0

更新プログラムをバッチしないようにするには、 'Update(dataTable)'が[文書化されています](http://msdn.microsoft.com/en-us/library/z1z2bkx2.aspx)であることに注意してください。文はバッチ・プロセスとして実行されず、各行は個別に更新されます」。バッチとトランザクションは、SQLでは直交する2つの概念です。 –

0

使用MERGE:むしろハードコーディング/動的SQLよりも

MERGE INTO TableName 
    USING (
      VALUES (1000, 5), 
       (1001, 10), 
       (1002, 30) 
     ) AS source (RowID, Column_name) 
     ON TableName.RowID = source.RowID 
WHEN MATCHED THEN 
    UPDATE 
     SET Column_name = source.Column_name 
WHEN NOT MATCHED THEN 
    INSERT (RowID, Column_name) 
     VALUES (RowID, Column_name); 

MERGE文はtable-valued parameterを取るストアドプロシージャにカプセル化することができます。

関連する問題