C#,SQL更新多行

13

我有一个关于通过SQL有效地更新多个行的问题。

基本上,我需要在不同的行ID上运行查询:

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#中构建更新查询命令(或者只是给我一个应该得到的结果查询的示例),这样一旦我使用ExecuteQuery,它将一次性运行所有这些命令,而不是执行每个命令。

编辑: 我有另一个问题,您能否解释一下动态情况,即可能并非我要更新的行已经存在,在这种情况下,我需要插入而不是更新。为了更好地解释,回到我的例子,假设我想要执行

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

我的意思是需要检查行是否存在,如果存在,则使用更新操作,否则必须插入它。

谢谢!


请确认您正在使用哪个数据库产品和版本?对于现代的 SQL Server(>= 2008),您需要使用表值参数和 MERGE 语句。 - Damien_The_Unbeliever
2个回答

9

您可以使用DataTable来存储记录,插入、删除或更改行,并通过使用SqlDataAdapter的UpdateBatchSize将所有更改一次性更新(0表示没有限制):

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/zh-cn/library/aadf8fk2.aspx

我猜您可能对数据库管理系统内部的工作方式存在误解。这

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

是相同的意思

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

即使您编写了像UPDATE table SET value=1这样会影响表中每条记录的语句,DBMS仍将逐一更新所有受影响的记录。通过批量更新,您可以确保所有更新(删除、插入)都提交到数据库,而不是为每个语句进行一次往返。


我正在查看更新的代码(因为它与我的问题最相关),但我并不完全理解最后得出的查询及其为什么有效?看起来好像你正在构建我想避免的查询,是吗? - Popokoko
1
无论您是否编写像UPDATE table SET value=1这样会影响表中每个记录的语句,DBMS都将逐一更新所有受影响的记录。通过一次性批量更新,您可以确保所有更新(删除、插入)在同一事务中一次性提交。 - Tim Schmelter
需要注意的是,Update(dataTable)已记录不会批量更新:“需要注意的是,这些语句不作为批处理过程执行;每行都会单独更新。”而且,在SQL中,批处理和事务是两个正交的概念。 - Damien_The_Unbeliever
@Damien_The_Unbeliever:当然,DataTable中每个修改过的行都会创建一个单独的更新/插入/删除语句。但是通过将DataAdapter的UpdateBatchSize设置为<>1,您可以避免为每个语句向数据库发送往返请求,而是将它们一起提交到一个批处理中。 - Tim Schmelter
@Damien_The_Unbeliever:针对你的第二个参数,你说得完全正确!你可以轻松地创建一个事务并将多个命令分配给它。抱歉将两者混为一谈。 - Tim Schmelter

1
使用 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);

与硬编码/动态SQL不同,MERGE语句可以封装到一个存储过程中,并使用表值参数


刚刚发现了这个网址:https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/。 - Kunal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接