35

我正在尝试将 .csv 文件插入到带有 unix 换行符的数据库中。我正在运行的命令是:

BULK INSERT table_name
FROM 'C:\file.csv' 
WITH 
( 
    FIELDTERMINATOR = ',', 
    ROWTERMINATOR = '\n' 
) 

如果我将文件转换为 Windows 格式,加载工作,但如果可以避免,我不想做这个额外的步骤。有任何想法吗?

4

8 回答 8

101

我觉得有必要做出贡献,因为我遇到了同样的问题,而且我每天至少需要从 SAP 读取 2 个 UNIX 文件几次。因此,我不需要使用 unix2dos,而是需要人工干预更少、通过编程更自动化的东西。

如前所述,Char(10) 在 sql 字符串中工作。我不想使用 sql 字符串,所以我使用了 ''''+Char(10)+'''',但由于某种原因,这没有编译。

工作得非常顺利的是:with (ROWTERMINATOR = '0x0a')

问题用 Hex 解决了!

希望这可以帮助某人。

于 2010-11-17T17:03:15.807 回答
14

感谢所有回答的人,但我找到了我喜欢的解决方案。

当您告诉 SQL Server ROWTERMINATOR='\n' 时,它会将其解释为 Windows 下的默认行终止符,实际上是“\r\n”(使用 C/C++ 表示法)。如果您的行终止符真的只是“\n”,您将不得不使用下面显示的动态 SQL。

DECLARE @bulk_cmd varchar(1000)
SET @bulk_cmd = 'BULK INSERT table_name
FROM ''C:\file.csv''
WITH (FIELDTERMINATOR = '','', ROWTERMINATOR = '''+CHAR(10)+''')'
EXEC (@bulk_cmd)

为什么你不能说 BULK INSERT ...(ROWTERMINATOR = CHAR(10)) 超出了我的范围。看起来您不能评估命令的 WITH 部分中的任何表达式。

上面所做的是创建一个命令字符串并执行它。巧妙地回避了创建附加文件或执行额外步骤的需要。

于 2009-01-26T14:16:06.540 回答
3

我确认语法

ROWTERMINATOR = '''+CHAR(10)+'''

与 EXEC 命令一起使用时有效。

如果您有多个 ROWTERMINATOR 字符(例如管道和 unix 换行符),则其语法为:

ROWTERMINATOR = '''+CHAR(124)+''+CHAR(10)+'''
于 2011-05-17T21:27:05.980 回答
2

它比这更复杂一点!当您告诉 SQL Server ROWTERMINATOR='\n' 时,它会将其解释为 Windows 下的默认行终止符,实际上是“\r\n”(使用 C/C++ 表示法)。如果您的行终止符真的只是“\n”,您将不得不使用上面显示的动态 SQL。我刚刚花了一个小时的大部分时间弄清楚为什么 \n 在与 BULK INSERT 一起使用时并不真正意味着 \n!

于 2009-05-28T12:04:23.663 回答
1

一种选择是使用bcp,并设置一个控制文件'\n'作为换行符。

尽管您已表示不希望这样做,但另一种选择是使用unix2dos将文件预处理为带有'\r\n'换行符的文件。

最后,您可以使用 上的FORMATFILE选项BULK INSERT。这将使用 bcp 控制文件来指定导入格式。

于 2009-01-26T14:00:19.940 回答
0

在我看来,可以采取两种一般途径:在 SQL 脚本中读取 CSV 或预先转换 CSV 的多种方法(bcp,unix2dos,如果它是一个 -时间之王,您甚至可以使用代码编辑器为您修复文件)。

但是你将不得不有一个额外的步骤!

如果此 SQL 是从程序启动的,您可能希望转换该程序中的行尾。在这种情况下,您决定自己编写转换代码,您需要注意以下几点: 1. 行尾可能是 \n 2. 或 \r\n 3. 甚至是 \r (Mac!) 4.很遗憾,可能有些行有 \r\n 而其他行有 \n,除非您控制 CSV 的来源,否则任何组合都是可能的

好的好的。可能性4是牵强的。它发生在电子邮件中,但这是另一回事。

于 2009-01-26T14:10:17.457 回答
0

我认为“ROWTERMINATOR = '\n'”会起作用。我建议在显示“隐藏字符”的工具中打开文件,以确保该行像您想象的那样被终止。我使用记事本++来处理这样的事情。

于 2009-01-26T14:37:11.100 回答
0

归结为这一点。Unix 使用 LF (ctrl-J),MS-DOS/Windows 使用 CR/LF (ctrl-M/Ctrl-J)。

当您在 Unix 上使用 '\n' 时,它会被转换为 LF 字符。在 MS-DOS/Windows 上,它被翻译成 CR/LF。当您的导入在 Unix 格式的文件上运行时,它只看到一个 LF。因此,首先通过 unix2dos 运行文件通常更容易。但是正如您在原始问题中所说的那样,您不想这样做(我认为您不能这样做是有充分理由的)。

为什么你不能这样做:

(ROWTERMINATOR = CHAR(10))

可能是因为在解析 SQL 代码时,它没有将 char(10) 替换为 LF 字符(因为它已经包含在单引号中)。或者也许它被解释为:

(ROWTERMINATOR =
     )

当您回显@bulk_cmd 的内容时会发生什么?

于 2009-01-26T16:48:51.660 回答