在单个事务中发送多个SQL命令

时间:2013-06-09 10:57:23

标签: c# .net sql-server

我有一个很大的INSERT INTO ...字符串列表。目前我用以下方式运行它们:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    foreach (var commandString in sqlCommandList)
    {
        SqlCommand command = new SqlCommand(commandString, connection);
        command.ExecuteNonQuery();
    }
}

我看到每个ExecuteNonQuery()也执行提交。

  1. 有没有办法在单个事务中插入所有行(最后提交)?
  2. 我想要一次交易的原因是让我的“插入”过程更快。单笔交易是否也能让它更快?

6 个答案:

答案 0 :(得分:32)

如果你在一个线程中执行多个查询,建议使用SQL事务,你可以这样:

    SqlTransaction trans; 

    try
    {
        SqlConnection connection = new SqlConnection(connectionString);
        connection.Open();

        trans = connection.BeginTransaction(); 

        foreach (var commandString in sqlCommandList)
        {
            SqlCommand command = new SqlCommand(commandString, connection,trans);
            command.ExecuteNonQuery();
        }

        trans.Commit(); 
    }
    catch (Exception ex) //error occurred
    {
        trans.Rollback();
        //Handel error
    }

答案 1 :(得分:9)

您可能只使用一个事务和命令就可以获得一些性能,如下所示:

using (SqlConnection connection = new SqlConnection(connectionString))
{
   try
   {
      connection.Open();

      using (SqlTransaction trans = connection.BeginTransaction())
      {
          using (SqlCommand command = new SqlCommand("", connection,trans))
          {
             command.CommandType = System.Data.CommandType.Text;

             foreach (var commandString in sqlCommandList)
             {
                command.CommandText = commandString;
                command.ExecuteNonQuery();
             }
          }

          trans.Commit();
       }        
    }
    catch (Exception ex) //error occurred
   {
       //Handel error
   }
}

答案 2 :(得分:0)

有点晚了,但如果要将所有值插入到同一个表中,请将SQL插入代码“插入tablex(f1,f2,f3,...)值(@ F1,@ F2,@ F3 ......)”。创建命令并添加参数@ F1 ...,然后在命令上设置Prepare标志。现在,当您遍历要插入的值列表时,可以将它们设置为适当的参数,然后执行ExecuteNonQuery。 SQL将预解析命令字符串一次,然后每次使用新参数。这有点快。

最后,您可以通过附加';'在单个命令中执行多个SQL语句如果必须执行整个字符串,则对每个语句。您可以将许多这些命令组合在一起,并向SQL服务器发出一个请求来执行它们。

答案 3 :(得分:0)

您可以将sql连接起来,让服务器处理它:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    string lsSql = string.Empty;
    foreach (var commandString in sqlCommandList)
    {
        lsSql = lsSql + commandString + " ; " + Environment.NewLine;
    }

    connection.Open();
    SqlCommand command = new SqlCommand(lsSql, connection);
    command.ExecuteNonQuery();
}

答案 4 :(得分:0)

这是我日常工作中使用的内容,然后对需要在数据库上运行的任何非查询使用foreach。您可以看到我正在使用OracleCommand,但是如果需要,可以更改为SQL语句

    public static void ExecuteDatabaseNonQuery(string command)
    {
        OracleCommand cmd = new OracleCommand();
        cmd.Connection = conn;

        OracleTransaction transaction;
        transaction = conn.BeginTransaction(IsolationLevel.ReadCommitted);
        cmd.Transaction = transaction;
        try
        {
            cmd.CommandText = command;
            var update = cmd.ExecuteNonQuery();
            transaction.Commit();

            Console.WriteLine("{0} rows updated", update);
        }
        catch (Exception e)
        {
            transaction.Rollback();
            throw new Exception("Error: " + e);
        }
    }

注意:如果数据库上有任何未提交的更改,此方法将无限期等待

答案 5 :(得分:-2)

您可以为每个

使用Parallel
   using (SqlConnection connection = new SqlConnection(connectionString))
    {
        List<string> sqlCommandList = new List<string>();
        connection.Open();
        Parallel.ForEach(sqlCommandList, commandString =>
        {
            SqlCommand command = new SqlCommand(commandString, connection);
            command.ExecuteNonQuery();
        });
    }