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

本文关键字:SQL 命令 单个 事务 | 更新日期: 2023-09-27 18:17:29

我有一个巨大的INSERT INTO ...字符串列表。目前我使用以下命令运行它们:

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

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

  1. 是否有一种方法可以在单个事务中插入所有行(最后提交)?
  2. 我想要单个事务的原因是使我的"插入"过程更快。单笔交易是否也会让它更快?

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

如果你在一个线程中执行多个查询,建议使用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
    }

仅使用一个事务和命令可能会获得一些性能,如下所示:

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
   }
}

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

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

您可以直接连接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();
}

这是我在日常工作中使用的,在使用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);
        }
    }

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

每个

可以使用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();
        });
    }