SQL Server BULK INSERT - 转义保留字符

5

关于在SQL Server BULK INSERT文件中转义字符的文档非常少。

BULK INSERT的文档称该语句只有两个格式选项:FIELDTERMINATORROWTERMINATOR,但它并没有说如果这些字符出现在一行的字段值中,应该如何转义它们。

例如,如果我有这个表:

CREATE TABLE People ( name varchar(MAX), notes varchar(MAX) )

并且这行数据:

"Foo, \Bar", "he has a\r\nvery strange name\r\nlol"

如果直接插入这些数据,显然是行不通的,那么对应的批量插入文件应该长什么样呢?

Foo,\Bar,he has a
very strange name
lol

SQL Server 表示支持 \r\n,但没有说明反斜杠是否需要转义,也没有提到字段值的分隔(例如使用双引号或转义双引号),所以我在这方面有些困惑。

3个回答

5
我用 \0 作为行分隔符,\t 作为字段分隔符来解决了这个问题,因为这两个字符都不会出现在字段值中,并且 BULK INSERT 支持它们作为分隔符。
我很惊讶 MSSQL 在导入/导出方面没有更多的灵活性。构建一个一流的 CSV/TSV 解析器并不需要太大的努力。

使用格式文件可以让您指定字段分隔符。 - Daniel Powell

2

以下内容供下一个搜索的人参考:

我使用"\0\t"作为字段分隔符,使用"\0\n"作为最后一个字段的行结束符。如果您想要假装文件具有DOS EOL约定,则可以使用"\0\r\n"。

对于那些不熟悉\x符号的人,\0是CHAR(0),\t是CHAR(9),\n是CHAR(10),\r是CHAR(13)。将CHAR()函数替换为您的语言提供的任何内容,以将数字转换为指定的字符。

使用此组合,所有\t和\n(以及\r)的实例都成为数据文件中可接受的字符。毕竟,批量上传系统的弱点在于制表符和换行符通常是文本字符串中合法的字符,而其他低ASCII字符(如CHAR(0),CHAR(1)和CHAR(2))则不是合法文本 - 甚至不会出现在UTF-8中。

您的数据中唯一不能有的字符是\0 - 除非您可以保证其后不会跟随\t或\n(或\r)

如果您的语言在字符串中使用\0时存在问题(但根据您的编码方式,您可能仍然能够避免该问题) - 并且如果您知道您的数据中不会有CHAR(1)或CHAR(2)(即没有二进制)),那么请改用这些字符。只有在尝试将任意二进制数据存储在字符串中时,才会发现这些低字符。

还要注意,您将在UTF-16、UCS-2和UTF-32(也称为UCS-4)中找到字节0、1、2 - 但是 - CHAR(0、1或2)的2或4字节宽表示仍然可接受,并且与任何合法的Unicode文本都不同。只需确保在格式文件中选择正确的代码页设置以适应您选择的UTF或UCS变体。


0

批量插入需要为每行设置相应的字段和字段计数。您的示例有些粗糙,因为它不是结构化数据。至于字符,它将按字面意义解释它们,而不使用转义字符(您的字符串将与文件中看到的一样)。

至于用双引号括起来的每个字段,您只需将它们用作字段和行终止符即可。所以现在你应该有:

Fieldterminator = '","', Rowterminator = '"\n'

这有意义吗?然后,在批量插入之后,您需要使用以下内容删除前缀双引号:

Update yourtable set yourfirstcolumn = right(yourfirstcolumn, len(yourfirstcolumn) - 1)


但是,如果我的数据包含这些字符串作为字段值的一部分,那么插入操作将失败。 - Dai
@David,你说得对。看看格式文件,它们可以为批量插入数据提供更多的灵活性。 - user596075

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接