20

我有一个巨大的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. 我想要一个事务的原因是让我的“插入”过程更快。单笔交易也会使其更快吗?
4

6 回答 6

41

如果您在一个线程中执行多个查询,建议使用 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
    }
于 2013-06-10T08:14:24.190 回答
14

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

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
   }
}
于 2013-10-02T16:12:35.757 回答
0

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

最后,您可以通过附加 ';' 在单个命令中执行多个 SQL 语句 到每个语句,如果你必须执行整个字符串。您可以将许多这样的命令捆绑在一起,然后向 SQL 服务器发出一个请求来执行它们。

于 2014-07-21T23:33:29.723 回答
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();
}
于 2019-05-24T09:25:34.800 回答
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);
        }
    }

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

于 2020-08-27T14:00:28.497 回答
-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();
        });
    }
于 2013-06-09T11:27:38.467 回答