【问题标题】:C# , SQL update multiple rowsC#,SQL 更新多行
【发布时间】:2012-02-23 09:14:18
【问题描述】:

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

基本上我有一个查询需要在不同的 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# 上构建更新查询命令(或者只是给我一个我应该得到的结果查询的示例)所以一旦我使用 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 语句

标签: c# sql


【解决方案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);

可以将MERGE 语句封装到采用table-valued parameter 的存储过程中,而不是硬编码/动态SQL。

【讨论】:

【解决方案2】:

您可以使用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/en-us/library/aadf8fk2.aspx

我假设您误解了 dbms 在内部的工作方式。这个

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);

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

【讨论】:

  • 我正在查看更新代码(因为它与我的问题最相关),我不太明白最后的查询结果是什么,为什么它有效?看起来你正在构建我试图避免的查询,不是吗?
  • dbms 无论如何都会一个一个地更新所有受影响的记录,即使您编写像UPDATE table SET value=1 这样的语句会影响表中的每条记录。通过批量更新,您可以确保所有更新(删除、插入)都在同一事务中一次提交。
  • 需要注意的是Update(dataTable)documented不是批量更新:“需要注意的是这些语句不是批处理执行的,每一行都是单独更新的。”,并且批处理和事务是 SQL 中的两个正交概念。
  • @Damien_The_Unbeliever:当然,DataTable 中的每个修改行都会创建一个单独的更新/插入/删除语句。但是通过将DataAdapter's UpdateBatchSize 设置为 1,您可以通过批量提交每个语句来避免往返数据库。
  • @Damien_The_Unbeliever:对于你的第二个论点,你完全正确!你可以很容易地create a Transaction and assign multiple commands 到它。很抱歉将两者混为一谈。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-04
  • 1970-01-01
  • 2012-02-09
  • 2014-10-26
  • 2013-01-15
相关资源
最近更新 更多