2

我正在使用批量插入将 csv 导入数据库。它是逗号分隔的 csv 文件。所有字段都没有文本限定符。

但有些字段可能有逗号作为数据的一部分。例如,地址字段值。这些值用双引号括起来。只有当字段值中包含逗号时才会出现这些双引号,否则值不会被双引号包围。因此,在某些行中,ADDRESS 值用双引号括起来,但在其他行中则不是。有没有办法在批量插入命令中指定文本限定符?

我尝试使用格式文件选项进行批量插入。

BULK INSERT Test_Imported FROM 'C:\test.csv' 
WITH (FIRSTROW=0,FIELDTERMINATOR = ',',ROWTERMINATOR = '\n',FORMATFILE = 'C:\test.Fmt')

但我无法将双引号作为格式文件中的可选文本限定符提及。

PS:这个函数实际上是更大模块的一部分,它是用c#编写的。批量插入命令是从 c# 调用的。

csv 文件来自另一个自动化系统的电子邮件。我无法控制 csv 文件的格式。大约有 150 列。每个 csv 文件中平均有 12000 行。忘记指定数据库。它是 SQL Server 2005。

4

5 回答 5

4

不幸的是,您必须对文件进行预处理以使其保持一致。SQL 批量操作在字段分隔符上拆分字符串。

一些选项:

  • 在 C# 中处理以将不被引号包围的逗号更改为管道 (|)
  • 将文件分成 2:“和非”文件。这仅在同一字段具有“

你说你无法控制格式,但你所拥有的是无法使用的......

于 2009-09-04T11:08:00.233 回答
4

Bulk Insert语句真的很糟糕,因为它不处理可选的限定符。

TextFieldParser类可以帮助我们清理文件(Microsoft.VisualBasic.FileIO.TextFieldParser

我粘贴了一个函数,该函数使用TextFieldParser类来清理分隔文件,以便您可以在批量插入语句中使用它。

String newDel = CleanDelimitedFile("c:\temp.csv",new String[] {","},"\t,\t");

这是一个清理分隔文件的函数。

    /// <summary>
    /// This function opens a delimited file and cleans up any string quantifiers
    /// </summary>
    /// <param name="FileFullPath">Full path of the delimited string</param>
    /// <param name="CurrentDelimiter">What string / character the file uses as the delimiter</param>
    /// <param name="NewDelimiter">What new delimiter string to use</param>
    /// <returns>Returns String representation of the new delimited file</returns>
    private static String CleanDelimitedFile(String FileFullPath, String[] CurrentDelimiter, String NewDelimiter) {

        //-- if the file exists stream it to host
        if (System.IO.File.Exists( FileFullPath )) {
            Microsoft.VisualBasic.FileIO.TextFieldParser cvsParser = null;
            System.Text.StringBuilder parseResults = new System.Text.StringBuilder();
            try {
                // new parser
                cvsParser = new Microsoft.VisualBasic.FileIO.TextFieldParser(FileFullPath);
                // delimited file has certain fields enclosed in quotes
                cvsParser.HasFieldsEnclosedInQuotes = true;
                // the current delimiter
                cvsParser.Delimiters = CurrentDelimiter;
                // iterate through all the lines of the file
                Boolean FirstLine = true;
                while (!cvsParser.EndOfData ) {
                    if (FirstLine) {
                        FirstLine = false;
                    }
                    else {
                      parseResults.Append("\n");  
                    }
                    Boolean FirstField = true;
                    // iterate through each field
                    foreach (String item in cvsParser.ReadFields()) {
                        if (FirstField) {
                            parseResults.Append(item);
                            FirstField = false;
                        } 
                        else {
                            parseResults.Append(NewDelimiter + item);
                        }
                    }

                }
                return parseResults.ToString();
            }
            finally {
                if (cvsParser != null) {
                    cvsParser.Close();
                    cvsParser.Dispose();
                }
            }
        }
        return String.Empty;
    }
于 2010-03-02T19:04:05.193 回答
1

可悲的是,SQL 2005 和 2008 导入 XLS 文件比 CSV 文件更顺畅。我从来没有反对过微软,但除非数据库管理的所有 ANSI 标准都发生了巨大的变化并且文本限定符的概念被放弃(我非常怀疑),否则这可能是 MS 的专有举措。SQL 2000 可以很好地处理文本限定符(不确定 BULK 命令,因为我一直只使用导入向导)。想象一下当我们迁移到 2005 年时我的惊讶,我不得不重新处理所有流程以不导入平面文件而是导入 XLS。我只花了 16 个小时(是的,两个工作日)得出这个结论,那一周我实际上失眠了,因为我对 MS 不允许使用文本限定符感到非常沮丧(我什至走进我的老板办公室为花了这么多时间在应该有的东西上道歉是一个 10 分钟的任务)。具有讽刺意味的是,您不能告诉 Excel 导出任何内容而不包括双引号文本限定符(或几乎任何其他软件导出器)。GRRRRRR。

所有这一切中最令人沮丧的部分是 SQL 2005 导入向导有一个定义文本限定符的地方!

......我敢说我在这次经历之后开始理解所有反 M$ 的言论!

于 2010-04-16T15:47:17.763 回答
0

我知道这是一个老问题,但我有一个 TSQL 方法来处理间歇性引号分隔符。它可能不漂亮,但它可能会帮助那些在这里找到方法的人:

  1. 导入文本文件,每行在一列中 - 一个字段。
  2. 使用下面的更新语句将引号之间的逗号更改为一些可识别的字符串,在这种情况下*&*
  3. 使用另一个更新语句去除所有引号。
  4. 使用 bcp 将数据导出到新的 CSV 文件中。
  5. 将新 CSV 文件中的所有字段批量导入到原始表中:现在没有引号,字段内的逗号是&,因此可以使用简单的逗号分隔导入。
  6. 使用另一个更新语句将&改回逗号。

UPDATE InitialTable SET BulkColumn = REPLACE(BulkColumn, SubString(BulkColumn, CHARINDEX('"', BulkColumn, 0), CHARINDEX('"', BulkColumn, CHARINDEX('"', BulkColumn, 0) + 1) - CHARINDEX('"', BulkColumn, 0) + 1), REPLACE( SubString(BulkColumn, CHARINDEX('"', BulkColumn, 0), CHARINDEX('"', BulkColumn, CHARINDEX('"', BulkColumn, 0) + 1) - CHARINDEX('"', BulkColumn, 0) + 1), ',', '*&*')) WHERE BulkColumn LIKE '%"%'

于 2015-05-20T21:49:17.320 回答
0

对我有用的是改变

ROWTERMINATOR = '\n'

到:

ROWTERMINATOR = '0x0a'
于 2019-07-24T06:42:21.337 回答