Reputation: 6543
i have a question regarding an efficient way to update multiple rows via SQL.
Basiclly i have a query i need to run on different RowIDs:
UPDATE TableName SET Column = (some number) WHERE RowID = (some number)
if to be more specific this is a better example:
UPDATE TableName SET Column = 5 WHERE RowID = 1000
UPDATE TableName SET Column = 10 WHERE RowID = 1001
UPDATE TableName SET Column = 30 WHERE RowID = 1002
..
I'd like to know how should i build the update query command on C# (or just give me an example of the resulted query i should get to) so once i use ExecuteQuery it will run all of these commands at one piece and not by executing each command.
edited: I have another problem, can you also explain what about dynamic situation in which not necessarly the row i want to update exist already, in that case i need to insert instead of update. to explain better, back to my example lets say i want to do
UPDATE TableName SET Column = 5 WHERE RowID = 1000
INSERT INTO TableName [RowID, Column] VALUES (1001, 20)
UPDATE TableName SET Column = 30 WHERE RowID = 1002
..
The meaning of this is that i need to check if the row exist, if so i'd use update otherwise i'll have to insert it.
Thank you!
Upvotes: 13
Views: 22349
Reputation: 57023
Use MERGE
:
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);
Rather than hard-coding/dynamic SQL, the MERGE
statement could be encapsulated into a stored proc that takes a table-valued parameter.
Upvotes: 1
Reputation: 460138
You could use a DataTable to store your records, insert, delete or change rows and update all changes in one batch by using SqlDataAdapter's UpdateBatchSize(0 means no limit):
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 "
+ "Name=@Name WHERE ProductCategoryID=@ProdCatID;",
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 ProductCategoryID=@ProdCatID;", 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
I assume you're misunderstanding how the dbms works internally. This
UPDATE TableName SET Column = 5 WHERE RowID = 1000;
UPDATE TableName SET Column = 5 WHERE RowID = 1002;
is the same as
UPDATE TableName SET Column = 5 WHERE RowID IN(1000,2002);
The dbms will update all affected records one by one anyway even if you would write a statement like UPDATE table SET value=1
which would affect every record in the table. By updating in one batch you ensure that all updates(deletes,inserts)are submitted to the database instead of one roundtrip for every statement.
Upvotes: 9