【问题标题】:Bulk insert into SQL table from CSV using C#使用 C# 从 CSV 批量插入 SQL 表
【发布时间】:2014-10-09 13:31:22
【问题描述】:

我需要从csv 文件将数据批量插入SQL。在 SQL 中,我使用以下命令:

bulk insert InputTestData
from 'D:\Project\UnitTestProjct\RGTestingToolTestProject\NUnitTestProject\RGTestToolDB\InputTestData.csv'
with
(   CODEPAGE ='RAW',
    rowterminator='\n',
    fieldterminator = '\t'
)

上述命令在使用 SQL 查询分析器时有效并插入数据,但在使用下面给出的代码从C# 执行时抛出错误:

 StringBuilder builder = new StringBuilder();
                                    builder.Append("bulk insert " + objectName + " from ");
                                    builder.Append("'" + ResourceFilePath + Path.DirectorySeparatorChar + objectPath + "'");
                                    builder.Append(" with");
                                    builder.Append(" (");                                       
                                    builder.Append(" rowterminator='\n',");
                                    builder.Append(" fieldterminator = '\t'");
                                    builder.Append(" )");

                                    SqlHelper.ExecuteNonQuery(transaction, CommandType.Text, builder.ToString());

它抛出错误:

Bulk load data conversion error (type mismatch or invalid character for the specified codepage) for row 1, column 8 (IsBaselineTest).

C# 代码生成的查询在 SQL 查询分析器中也可以正常工作:

bulk insert InputTestData from 'D:\Project\UnitTestProjct\RGTestingToolTestProject\NUnitTestProject\\RGTestToolDB\InputTestData.csv' with ( rowterminator='
', fieldterminator = '  ',CODEPAGE ='RAW' )

如果您需要CSVSQL 表结构,请告诉我

请在上面提供帮助。

提前致谢

【问题讨论】:

  • 您是否在查询分析器中测试了您的StringBuilder 生成的查询?
  • 是的,它的工作,我已经更新了该查询也有问题的块
  • 您在 c# 中构建的字符串缺少参数CODEPAGE。如果你把它加回去有什么变化吗?
  • 我无法直接回答您,但您可以尝试使用专为此场景设计的 System.Data.SqlClient.SqlBulkCopy 类。
  • 我很确定您必须为行和字段终止符转义反斜杠,因为看起来字符串已经将它们转换为实际字符 0x10 和 0x09。我认为它必须是 builder.Append(" rowterminator='\\n',"); builder.Append("fieldterminator = '\\t'");

标签: c# sql sql-server bulkinsert sqlbulkcopy


【解决方案1】:

我很确定你必须为行和字段终止符转义反斜杠,因为看起来字符串已经将它们转换为实际字符 0x10 和 0x09。我认为它必须是

builder.Append(" rowterminator='\\n',"); 
builder.Append(" fieldterminator = '\\t'");

【讨论】:

    【解决方案2】:

    我刚刚按照一些评论的建议使用 SqlBulkCopy 完成了一项类似的任务。

    我的源是一个 XML 文档,但情况非常相似。

    我开发的解决方案是上传数据的 Web 界面,一些代码将其放入数据表中,然后调用 SqlBulkCopy 以插入临时表。

    最后一步是将数据插入最终表的查询,处理重复项并执行一些验证。

    这是一些代码(实际上是 vb.net):

    ' create in memory datatable
    ' my choice has been to have the same datatype for all fields
    Dim sapCustomer As DataTable = New DataTable("customer")
    For Each SAPFieldName As String In SAPColMapping
      sapCustomer.Columns.Add(New DataColumn(SAPFieldName, GetType(System.String)))
    Next
    
    ' fill previous table using xml data
    For Each SapRow As XmlNode In RowList.SelectNodes("ROW")
      ... more code here to translate xml into datatable...
    Next
    
    ' create temporary table on sql server
    Using dbCmd As SqlCommand = New SqlCommand
      dbCmd.Connection = dbConn
      dbCmd.Transaction = dbTran
      dbCmd.CommandType = CommandType.Text
      dbCmd.CommandText = "create table #tempTable (your fields here)"
      dbCmd.ExecuteNonQuery
    End Using
    
    ' fill temp table
    Using sbc As SqlBulkCopy = New SqlBulkCopy(dbConn, SqlBulkCopyOptions.Default, dbTran)
      sbc.BatchSize = 1000
      ' no explicit mapping between source and destination fields
      ' because both tables have the very same field names
      sbc.DestinationTableName = "#tempTable"
      sbc.WriteToServer(sapCustomer)
    End Using
    
    ' handle the steps needed to copy/move the data to the final destination
    Using dbCmd As SqlCommand = New SqlCommand
      dbCmd.Connection = dbConn
      dbCmd.Transaction = dbTran
      dbCmd.CommandType = CommandType.Text
      dbCmd.CommandText = "insert into finaltable select field1, field2 from #tempTable"
      dbCmd.ExecuteNonQuery
    End Using
    

    上述代码在 1 分钟内成功处理了 50mb+ 和 50k 条记录的 xml 文档。

    繁重的任务是将数据从 xml 复制到数据表:上传一堆 sec,xml 40 sec -> datatable 和数据库处理 2 sec。

    如果您的数据采用更“数据表友好”的格式,您可能会轻松获得更好的性能。

    【讨论】:

      猜你喜欢
      • 2013-02-05
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-01
      相关资源
      最近更新 更多