我正在尝试将.csv文件插入带有unix换行符的数据库中。我正在运行的命令是:
BULK INSERT table_name
FROM 'C:\file.csv'
WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n'
)
如果我将文件转换为Windows格式,则加载有效,但如果可以避免,我不想执行此额外步骤。有什么想法吗?
答案 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的内容时会发生什么?