【问题标题】:How to insert into SQL Server database in a batch?如何批量插入SQL Server数据库?
【发布时间】:2019-01-30 21:42:30
【问题描述】:

我们执行 SQL Server 存储过程mySP 插入数据库(假设它会调用存储过程大约 300,000 次)。

ALTER PROCEDURE [dbo].[mySP]
    @ThePath VARCHAR(255),
    @TheID INT
AS
    INSERT INTO myTbl (TheTime, ThePath, TheID)
    VALUES (GETDATE(), @ThePath, @TheID)

这是执行存储过程mySP的代码:

using (SqlConnection con = new SqlConnection(connectionString))
{
:
     foreach (.....)  //about 300,000 times
     {
         SqlCommand MyCmd = new SqlCommand("mySP", con);
         MyCmd.CommandType = CommandType.StoredProcedure;
         MyCmd.Parameters.Add(new SqlParameter("ThePath", sMyPath));
         MyCmd.Parameters.Add(new SqlParameter("TheID", sMyID));

         iRow = MyCmd.ExecuteNonQuery();

         MyCmd.Dispose();
         MyCmd = null;
     }
}

如何在一批说 5000 的情况下执行此操作,然后提交事务?

谢谢

【问题讨论】:

  • 你为什么不通过 SP 做呢?用你想要的批号在 SP 内循环。
  • 您好,我需要在应用程序中执行循环以获取需要插入数据库的信息。
  • 批处理意味着编写多语句SQL。不需要循环。批处理多个插入也不会使它们更快,它节省了网络往返。另一方面,批量插入确实通过使用最少的日志记录来提高性能。您可以使用bcp 命令、the BULK INSERT` 语句或 SqlBulkCopy 类来批量插入数据
  • SqlBulkCopy 可以接受 DataTabel 或 DataReader 作为源,这意味着您可以将其他数据库查询的结果提供给它

标签: .net sql-server stored-procedures c#-4.0 sqlcommand


【解决方案1】:

当一次插入数千行时,最好使用 .Net 自己的 SqlBulkCopy 之类的东西,这基本上意味着您必须先填充 DataTable,然后使用 SqlBulkCopy 将其写入数据库。请参阅https://sqlbulkcopy-tutorial.net/ 以获得很好的示例。一个小建议是玩弄 BatchSize 属性;通常保持原样就足够了。不要忘记也使用事务。

例子:

using (SqlConnection connection = new SqlConnection("server=local);database=MyDatabase;integrated security=SSPI"))
{
    connection.Open();

    DirectoryInfo directory = new DirectoryInfo(@"C:\Temp\");

    var files = directory.GetFiles("*.dat");

    foreach (var file in files)
    {
        if (file.Length > 0)
        {
            string fileName = Path.GetFileNameWithoutExtension(file.FullName);

            SqlCommand cmd = new SqlCommand("dbo.uspStagingGetTableStructure", connection);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.AddWithValue("@tableName", fileName);

            using (SqlDataReader reader = cmd.ExecuteReader())
            {
                while (reader.Read())
                {
                }
            }

            //
            // Prepare Bulkcopy target (datatable)
            //

            string target = "MyBulkCopyTarget";

            DataTable dataTable = new DataTable(target);
            SqlBulkCopy bulkcopy = new SqlBulkCopy(connection);
            bulkcopy.DestinationTableName = target;
            bulkcopy.BulkCopyTimeout = 600;

            //
            // Map columns source -> target
            //

            //foreach (var dataField in dataFields)
            //{
            //    if (dataField.sqlDbType == SqlDbType.Int)
            //        dataTable.Columns.Add(dataField.fieldName, typeof(int));
            //    else
            //        dataTable.Columns.Add(dataField.fieldName, typeof(string));
            //    bulkcopy.ColumnMappings.Add(dataField.fieldName, dataField.fieldName);
            //}

            //
            // Populate Bulkcopy target (datatable)
            //

            string line = string.Empty;
            using (StreamReader reader = file.OpenText())
            {
                while ((line = reader.ReadLine()) != null)
                {
                    DataRow row = dataTable.NewRow();

                    //
                    // Use proper data types
                    //

                    //foreach (var dataField in dataFields)
                    //{
                    //    if (dataField.sqlDbType == SqlDbType.Int)
                    //        row[dataField.fieldName] = Convert.ToInt32(line.Substring(dataField.fieldStartPos, dataField.fieldLength));
                    //    else
                    //        row[dataField.fieldName] = line.Substring(dataField.fieldStartPos, dataField.fieldLength);
                    //}

                    dataTable.Rows.Add(row);
                }
            }

            //
            // Push datatable to server
            //

            bulkcopy.WriteToServer(dataTable);
        }
    }
}
}
}

【讨论】:

  • 嗨,就我而言,由于我在应用程序中执行了一个 foreach 循环来获取输入数据,我该如何执行 sqlbulkCopy ?我不想在循环内执行存储过程 mySP,而是要在循环内填充 DataTable,然后 sqlbulkCopy 数据表?
  • 是的,请看我添加的示例。
  • 否 - 不要使用或推荐addwithvalue
  • 谢谢泰洛。我会试试的。
【解决方案2】:

在 SQL Server 中创建类型并将表作为参数传递。请往下看

How to pass table value parameters to stored procedure from .net code

https://www.c-sharpcorner.com/UploadFile/ff2f08/table-value-parameter-use-with-C-Sharp/

一旦将表变量传递给存储过程,就可以在一个插入选择语句中插入数据。

【讨论】:

  • 嗨 Maddy/Marc_s..with 表值参数,我们是否插入一些记录然后提交(如 SqlBulkCopy)?我担心的是我不想填满数据库事务日志,所以我想插入说 5000 条记录,然后提交,然后接下来的 5000 条记录然后提交,等等。
  • 是的,我们可以根据您的需要插入 n 条记录。为数据表中的 5000 行创建循环并调用 store proc。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-16
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多