4

我有一个来自另一个数据库的 CSV 转储,看起来像这样(id、name、notes):

1001,John Smith,15 Main Street
1002,Jane Smith,"2010 Rockliffe Dr.
Pleasantville, IL
USA"
1003,Bill Karr,2820 West Ave.

最后一个字段可能包含回车和逗号,在这种情况下,它被双引号括起来。我需要保留这些返回值和逗号。

我使用此代码将 CSV 导入到我的表中:

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

SQL Server 2005批量插入无法确定引号内的回车符不是行终止符
如何克服?


更新
看起来在字段内保留换行符的唯一方法是使用不同的行分隔符。所以,我想通过在它们前面放置一个管道来标记所有行分隔换行符。如何将我的 CSV 更改为如下所示?

1001,约翰史密斯,15 Main Street|
1002,Jane Smith,"2010 Rockliffe Dr.
Pleasantville, IL
USA"|
1003,Bill Karr,2820 West Ave.|

4

6 回答 6

1

SQL Server 上的批量操作并不特别支持 CSV,即使它们可以在文件经过仔细格式化的情况下导入它们。我的建议是将所有字段值括在引号中。BULK INSERT 可能会允许在字段值内回车。如果没有,那么您的下一个解决方案可能是集成服务包。

有关更多信息,请参阅为批量导出或导入准备数据

于 2010-03-25T04:08:25.733 回答
1

您可以使用脚本将这些换行符合并为一行,例如,您可以使用 GNU sed删除换行符。例如

$ more file
1001,John Smith,15 Main Street
1002,Jane Smith,"2010 Rockliffe Dr.
Pleasantville, IL
USA"
1003,Bill Karr,"2820
West Ave"

$ sed '/"/!s/$/|/;/.*\".*[^"]$/{ :a;N };/"$/ { s/$/|/ }' file
1001,John Smith,15 Main Street|
1002,Jane Smith,"2010 Rockliffe Dr.
Pleasantville, IL
USA"|
1003,Bill Karr,"2820
West Ave"|

然后你可以批量插入。

编辑:

保存这个:/"/!s/$/|/;/.*\".*[^"]$/{ :a;N };/"$/ { s/$/|/ }在一个文件中,比如说myformat.sed。然后在命令行上执行此操作

c:\test> sed.exe -f myformat.sed myfile

于 2010-03-25T09:06:35.233 回答
0

根据所有知识的来源(维基百科),csv使用新行来分隔记录。所以你所拥有的不是有效的csv。

我的建议是您编写一个 perl 程序来处理您的文件并将每条记录添加到数据库中。

如果您不是 perl 人,那么您可以使用编程站点或查看某种 SO 人是否会为您编写程序的解析部分。

添加:

可能的解决方案

由于 OP 声明他可以更改输入文件,我会将所有不遵循 " 的新行更改为保留的字符序列,例如 XXX

这可以是许多编辑器中的自动替换。在 Windows 中,UltraEdit 包括正则表达式查找/替换功能

然后导入 dbms,因为您将不再拥有嵌入的新行。

然后使用 SQL Replace将出现的 XXX 更改回新行。

于 2010-03-25T03:42:01.860 回答
0

如果您可以控制 CSV 文件的内容,则可以将字段内换行符 ( CRLF) 替换为非换行符(可能只是CRLF),然后在导入后运行脚本以CRLF再次替换它们。

这就是 MS Office 产品(Excel、Access)处理这个问题的方式。

于 2010-03-25T08:06:08.470 回答
0

好的,这是我最终编写的一个小型 Java 程序来解决问题。
欢迎评论、更正和优化。

import java.io.*;

public class PreBulkInsert
{
    public static void main(String[] args)
    {
        if (args.length < 3)
        {
            System.out.println ("Usage:");
            System.out.println ("  java PreBulkInsert input_file output_file separator_character");
            System.exit(0);
        }

        try
        {
            boolean firstQuoteFound = false;
            int fromIndex;
            int lineCounter = 0;
            String str;

            BufferedReader in = new BufferedReader(new FileReader(args[0]));
            BufferedWriter out = new BufferedWriter(new FileWriter(args[1])); 
            String newRowSeparator = args[2];

            while ((str = in.readLine()) != null)
            {
                fromIndex = -1;
                do
                {
                    fromIndex = str.indexOf('"', fromIndex + 1);
                    if (fromIndex > -1)
                        firstQuoteFound = !firstQuoteFound;
                } while (fromIndex > -1);

                if (!firstQuoteFound)
                    out.write(str + newRowSeparator + "\r\n");
                else
                    out.write(str + "\r\n");
                lineCounter++;
            }
            out.close();
            in.close();
            System.out.println("Done! Total of " + lineCounter + " lines were processed.");
        }
        catch (IOException e)
        {
            System.out.println(e.getMessage());
            System.exit(1);
        }       
    }
}
于 2010-03-26T04:05:19.857 回答
-1

除非 CSV 格式有效,否则无法导入。因此,您必须修复转储或手动使用搜索和替换修复不需要的换行符。

于 2010-03-25T04:16:22.547 回答