将整个DataTable一次性插入数据库而不是逐行插入?

Kyl*_*yle 27 c# sql sql-server

我有一个DataTable,需要将整个事物推送到Database表.

我可以使用foreach并一次插入每一行来获取所有内容.这非常缓慢,因为有几千行.

有没有办法一次完成整个数据表可能更快?

DataTable的列数少于SQL表.其余的应该留空.

Kyl*_*yle 60

我发现SqlBulkCopy是一种简单的方法,并且不需要在SQL Server中编写存储过程.

以下是我如何实现它的示例:

// take note of SqlBulkCopyOptions.KeepIdentity , you may or may not want to use this for your situation.  

using (var bulkCopy = new SqlBulkCopy(_connection.ConnectionString, SqlBulkCopyOptions.KeepIdentity))
{
      // my DataTable column names match my SQL Column names, so I simply made this loop. However if your column names don't match, just pass in which datatable name matches the SQL column name in Column Mappings
      foreach (DataColumn col in table.Columns)
      {
          bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
      }

      bulkCopy.BulkCopyTimeout = 600;
      bulkCopy.DestinationTableName = destinationTableName;
      bulkCopy.WriteToServer(table);
}
Run Code Online (Sandbox Code Playgroud)

  • 我发现它很有帮助.别这么迟钝了. (10认同)
  • 如果没有有用的信息,我不确定答案来自哪里.我之所以提出一个新的原因,是因为评论不再对改进的答案有意义,而且与问题无关. (7认同)
  • @AaronBertrand我之前的答案只是"SQL Bulk Copy",没有细节.我删除了它并用这个详细的替换它.在许多情况下,需要一个SP是不错的.我从来没有说过它很糟糕,我只是提供一个不需要它的解决方案. (5认同)
  • 像这样的@AaronBertrand"答案"是我避免SO的原因.凯尔的帖子正是我在这种特殊情况下所寻找的.不幸的是,我通过你的挑剔来找到它. (2认同)

Aar*_*and 31

由于您已经拥有DataTable,并且由于我假设您使用的是SQL Server 2008或更高版本,因此这可能是最简单的方法.首先,在您的数据库中,创建以下两个对象:

CREATE TYPE dbo.MyDataTable -- you can be more speciifc here
AS TABLE
(
  col1 INT,
  col2 DATETIME
  -- etc etc. The columns you have in your data table.
);
GO

CREATE PROCEDURE dbo.InsertMyDataTable
  @dt AS dbo.MyDataTable READONLY
AS
BEGIN
  SET NOCOUNT ON;

  INSERT dbo.RealTable(column list) SELECT column list FROM @dt;
END
GO
Run Code Online (Sandbox Code Playgroud)

现在在您的C#代码中:

DataTable tvp = new DataTable();
// define / populate DataTable

using (connectionObject)
{
    SqlCommand cmd = new SqlCommand("dbo.InsertMyDataTable", connectionObject);
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter tvparam = cmd.Parameters.AddWithValue("@dt", tvp);
    tvparam.SqlDbType = SqlDbType.Structured;
    cmd.ExecuteNonQuery();
}
Run Code Online (Sandbox Code Playgroud)

如果您在问题中提供了更具体的细节,我会给出一个更具体的答案.


jal*_*eel 6

考虑这种方法,您不需要 for 循环:

using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
    bulkCopy.DestinationTableName = 
        "dbo.BulkCopyDemoMatchingColumns";

    try
    {
        // Write from the source to the destination.
        bulkCopy.WriteToServer(ExistingSqlTableName);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 对于像我这样的新手:bulkCopy.WriteToServer(ExitingSqlTableName); 这里ExistingSqlTableName表示现有的sql数据源。它可以是 SQL 表、数据表或读取器。 (3认同)