批量插入,SQL Server 2000,unix换行符

时间:2009-01-26 13:37:17

标签: sql sql-server bulkinsert

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

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

如果我将文件转换为Windows格式,则加载有效,但如果可以避免,我不想执行此额外步骤。有什么想法吗?

8 个答案:

答案 0 :(得分:98)

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

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

工作非常灵活的是:(ROWTERMINATOR ='0x0a')

Hex解决了问题!

希望这有助于某人。

答案 1 :(得分: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部分中的任何表达式。

以上操作是创建命令的字符串并执行该命令。巧妙地回避了创建附加文件或执行额外步骤的需要。

答案 2 :(得分:3)

我确认语法

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

与EXEC命令一起使用时。

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

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

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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

虽然您已表示不愿意,但另一种选择是使用unix2dos将文件预处理为'\r\n'换行符。

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

答案 5 :(得分:0)

在我看来,可以采取两种常规途径:在SQL脚本中读取CSV的一些替代方法,或者使用您可以执行此操作的众多方法之前转换CSV(bcp,unix2dos,如果是作为一件事的一次性王者,您甚至可以使用代码编辑器为您修复文件。

但你必须有一个额外的步骤!

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

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

答案 6 :(得分:0)

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

答案 7 :(得分: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代码时,它并没有用LF字符替换char(10)(因为它已经包含在单引号中)。或者它可能被解释为:

(ROWTERMINATOR =
     )

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