【问题标题】:SQL Bulk import from CSV从 CSV 批量导入 SQL
【发布时间】:2008-09-18 20:17:14
【问题描述】:

我需要将一个大型 CSV 文件导入 SQL 服务器。我正在使用这个:

BULK 
INSERT CSVTest
        FROM 'c:\csvfile.txt'
            WITH
    (
                FIELDTERMINATOR = ',',
                ROWTERMINATOR = '\n'
    )
GO

问题是我的所有字段都被引号(“”)包围,所以一行实际上看起来像:

"1","","2","","sometimes with comma , inside", "" 

我能否以某种方式批量导入它们并告诉 SQL 使用引号作为字段分隔符?

编辑:使用 '","' 作为分隔符的问题,如建议的示例所示: 大多数示例所做的是,他们导入数据,包括第一列中的第一个“和最后一列中的最后一个”,然后他们继续将其删除。唉,我的第一列(也是最后一列)是日期时间,不允许将“20080902 作为日期时间导入”。

从我一直在阅读的内容来看,我认为 FORMATFILE 是可行的方法,但文档(包括 MSDN)非常无用。

【问题讨论】:

  • 您应该重新标记此 sqlserver,以便我们知道您使用的是什么数据库。

标签: sql sql-server tsql bulkinsert


【解决方案1】:

试试FIELDTERMINATOR='","'

这里有一个很好的链接,可以帮助你理解第一个和最后一个引号......看看他如何使用子字符串 SP

http://www.sqlteam.com/article/using-bulk-insert-to-load-a-text-file

【讨论】:

  • 它不起作用 :-(。表中的第一个字段是日期时间,它将导入前导引号 ("),生成错误
  • 还要注意导出 CSV 并引用字符串但未引用数字的应用程序。
  • 也为我工作。我使用的是 xml 格式文件,因此使用了 Terminator 属性而不是 FIELDTERMINATOR。另外,在我的最后一列中,我使用了以下 TERMINATOR='"\r\n'
【解决方案2】:

我有时使用的另一个技巧是在 Excel 中打开 CSV,然后将您的 sql 语句写入每行末尾的单元格中。 例如:

=concatenate("insert into myTable (columnA,columnB) values ('",a1,"','",b1,"'")")

向下填充可以为您填充到每一行。然后只需将输出复制并粘贴到新的查询窗口中即可。

这是老派,但如果您只需要偶尔进行一次导入,则可以省去阅读所有关于“正确”方法的晦涩文档的麻烦。

【讨论】:

  • 我知道这个答案很古老,但我刚到这里用谷歌搜索类似的东西。这是您想从表格数据生成任何代码的好时机,而不仅仅是加载 SQL 语句的代码。您可以在 Excel 文件中的某处放置一个模板,然后执行=SUBSTITUTE($Z$999, "placeholder_a", "'" & SUBSTITUTE(A2, "'", "''") & "'"), "placeholder_b", SUBSTITUTE(B2, "'", "''"))。假设您有一个 999 美元的模板。
【解决方案3】:

试试OpenRowSet。这可用于导入 Excel 内容。 Excel 可以打开 CSV 文件,因此您只需要找出正确的 [ConnectionString][2]。

[2]: Driver={Microsoft Text Driver (*.txt; *.csv)};Dbq=c:\txtFilesFolder\;Extensions=asc,csv,tab,txt;

【讨论】:

    【解决方案4】:

    我知道这不是一个真正的解决方案,但我使用虚拟表进行导入,并为所有内容设置了 nvarchar。然后我做了一个插入,去掉 " 字符并进行转换。它不是很漂亮,但它可以完成工作。

    【讨论】:

    • 引号之间可能有逗号,如何拆分字段?
    【解决方案5】:

    我说使用 FileHelpers 它是一个开源库

    【讨论】:

      【解决方案6】:

      您需要以编程方式执行此操作,还是一次性完成?

      使用企业管理器,右键单击导入数据可让您选择分隔符。

      【讨论】:

        【解决方案7】:

        您必须注意 BCP/BULK INSERT,因为如果引用不一致,BSP 或 Bulk Insert 都不能很好地处理这个问题,即使是格式文件(即使是 XML 格式文件也不提供选项)和虚拟 ["]开头和结尾的字符并使用 [","] 作为分隔符。从技术上讲,如果没有嵌入 [,] 字符,CSV 文件不需要有 ["] 字符

        正是由于这个原因,逗号分隔的文件有时被称为喜剧限制文件。

        OpenRowSet 需要服务器上的 Excel,并且在 64 位环境中可能会出现问题 - 我知道在 64 位的 Jet 中使用 Excel 会出现问题。

        如果文件将来可能与您的预期有所不同,SSIS 确实是您的最佳选择。

        【讨论】:

          【解决方案8】:

          如果你愿意,你可以试试这个非常可爱的代码, 这将从您的代码中删除不需要的分号。 例如,如果您的数据是这样的:
          "Kelly","Reynold","kelly@reynold.com"

          Bulk insert test1
          from 'c:\1.txt' with ( 
              fieldterminator ='","'
              ,rowterminator='\n')
          
          update test1<br>
          set name =Substring (name , 2,len(name))
          where name like **' "% '**
          
          update test1
          set email=substring(email, 1,len(email)-1)
          where email like **' %" '**
          

          【讨论】:

            【解决方案9】:

            首先您需要将 CSV 文件导入数据表中

            然后您可以使用 SQLBulkCopy 插入批量行

            using System;
            using System.Data;
            using System.Data.SqlClient;
            
            namespace SqlBulkInsertExample
            {
                class Program
                {
                  static void Main(string[] args)
                    {
                        DataTable prodSalesData = new DataTable("ProductSalesData");
            
                        // Create Column 1: SaleDate
                        DataColumn dateColumn = new DataColumn();
                        dateColumn.DataType = Type.GetType("System.DateTime");
                        dateColumn.ColumnName = "SaleDate";
            
                        // Create Column 2: ProductName
                        DataColumn productNameColumn = new DataColumn();
                        productNameColumn.ColumnName = "ProductName";
            
                        // Create Column 3: TotalSales
                        DataColumn totalSalesColumn = new DataColumn();
                        totalSalesColumn.DataType = Type.GetType("System.Int32");
                        totalSalesColumn.ColumnName = "TotalSales";
            
                        // Add the columns to the ProductSalesData DataTable
                        prodSalesData.Columns.Add(dateColumn);
                        prodSalesData.Columns.Add(productNameColumn);
                        prodSalesData.Columns.Add(totalSalesColumn);
            
                        // Let's populate the datatable with our stats.
                        // You can add as many rows as you want here!
            
                        // Create a new row
                        DataRow dailyProductSalesRow = prodSalesData.NewRow();
                        dailyProductSalesRow["SaleDate"] = DateTime.Now.Date;
                        dailyProductSalesRow["ProductName"] = "Nike";
                        dailyProductSalesRow["TotalSales"] = 10;
            
                        // Add the row to the ProductSalesData DataTable
                        prodSalesData.Rows.Add(dailyProductSalesRow);
            
                        // Copy the DataTable to SQL Server using SqlBulkCopy
                        using (SqlConnection dbConnection = new SqlConnection("Data Source=ProductHost;Initial Catalog=dbProduct;Integrated Security=SSPI;Connection Timeout=60;Min Pool Size=2;Max Pool Size=20;"))
                        {
                            dbConnection.Open();
                            using (SqlBulkCopy s = new SqlBulkCopy(dbConnection))
                            {
                                s.DestinationTableName = prodSalesData.TableName;
            
                                foreach (var column in prodSalesData.Columns)
                                    s.ColumnMappings.Add(column.ToString(), column.ToString());
            
                                s.WriteToServer(prodSalesData);
                            }
                        }
                    }
                }
            }
            

            【讨论】:

              【解决方案10】:

              这是一个老问题,所以我写这篇文章是为了帮助任何偶然发现它的人。

              SQL Server 2017 引入了 FIELDQUOTE 参数,该参数适用于这个确切的用例。

              【讨论】:

                【解决方案11】:

                是的,K Richard 是对的:FIELDTERMINATOR = '","'

                请参阅http://www.sqlteam.com/article/using-bulk-insert-to-load-a-text-file 了解更多信息。

                【讨论】:

                  【解决方案12】:

                  您也可以使用 DTS 或 SSIS。

                  【讨论】:

                    【解决方案13】:

                    您可以控制输入格式吗? | (管道),而 \t 通常是更好的字段终止符。

                    【讨论】:

                      【解决方案14】:

                      如果您知道如何将文件解析为 DataTable,我建议使用 SqlBulkInsert 类将其插入 SQL Server。

                      【讨论】:

                        猜你喜欢
                        • 2013-02-05
                        • 2014-09-03
                        • 2017-05-30
                        • 1970-01-01
                        • 2020-11-09
                        • 1970-01-01
                        • 2013-10-29
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多