如何在 SQL Server 2017 中使用批量插入和 XML 格式文件加载 UTF-8 CSV 文件
How to load UTF-8 CSV files using Bulk Insert and an XML Format file in SQL Server 2017
经过多次尝试,我发现自 SQL server 2017
(2016 年?)以来,通过使用选项 CODEPAGE = 65001
和 [=15] 可以通过批量插入加载 UTF-8 编码的 CSV 文件=],如其他一些问题中所述。
似乎不起作用的是在使用 XML 格式文件时做同样的事情。我通过仍然使用 CODEPAGE 和 DATAFILETYPE 选项尝试了这个,并且还省略了这些选项。我已经用最简单的数据集试过了。一行,一列,包含一些带有 UTF-8 字符的文本。
这是我正在使用的 XML 格式文件。
<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<FIELD ID="STREET" xsi:type="NCharTerm" TERMINATOR="\r\n" MAX_LENGTH="1000" COLLATION="Latin1_General_CS_AS_WS"/>
</RECORD>
<ROW>
<COLUMN SOURCE="STREET" NAME="STREET" xsi:type="SQLNVARCHAR"/>
</ROW>
</BCPFORMAT>
即使源数据只包含一些带有 1 个特殊字符的文本,最终结果如下所示:慊潫ⵢ瑓晥慦瑓慲鿃㐱
当使用 xsi:type="CharTerm"
而不是 xsi:type="NCharTerm"
时,结果如下所示: ...-Straßs
...
我是不是做错了什么,或者 XML 格式文件没有正确实现 UTF-8 支持?
将终结符更改为 TERMINATOR="\r[=10=]\n[=10=]"
。使用 NCharTerm 时,您必须考虑额外的字节数。
在尝试了这个之后,我找到了解决方案。
备注
- 无论有没有 BOM 表头,这都适用。这无关紧要。
- 罪魁祸首使用了 XML 文件中的 COLLATION 参数。省略它解决了编码问题。我对为什么会这样有直觉,但也许有更多见识的人可以在评论中解释...
DATAFILETYPE = 'char'
选项似乎没有必要。
- 在XML文件中,字段的
xsi:type
需要是CharTerm,不是NCharTerm。
- 这适用于 \r\n、\n 或 \r。只要您正确设置了 TERMINATOR,它就可以工作。不需要 \n[=55=] 变化(这甚至会破坏功能,因为这不是 UTF-16 或 UCS-2)。
您可以在下方找到便于重复使用的概念验证...
data.txt
ß
ß
ß
Table
CREATE TABLE [dbo].[TEST](
TEST [nvarchar](500) NULL
)
formatfile.xml
<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<FIELD ID="1" xsi:type="CharTerm" TERMINATOR="\r\n" MAX_LENGTH="20"/>
</RECORD>
<ROW>
<COLUMN SOURCE="1" NAME="TEST" xsi:type="SQLNVARCHAR"/>
</ROW>
</BCPFORMAT>
批量插入
bulk insert TEST..TEST
from 'data.txt'
with (formatfile = 'formatfile.xml', CODEPAGE = 65001)
经过多次尝试,我发现自 SQL server 2017
(2016 年?)以来,通过使用选项 CODEPAGE = 65001
和 [=15] 可以通过批量插入加载 UTF-8 编码的 CSV 文件=],如其他一些问题中所述。
似乎不起作用的是在使用 XML 格式文件时做同样的事情。我通过仍然使用 CODEPAGE 和 DATAFILETYPE 选项尝试了这个,并且还省略了这些选项。我已经用最简单的数据集试过了。一行,一列,包含一些带有 UTF-8 字符的文本。
这是我正在使用的 XML 格式文件。
<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<FIELD ID="STREET" xsi:type="NCharTerm" TERMINATOR="\r\n" MAX_LENGTH="1000" COLLATION="Latin1_General_CS_AS_WS"/>
</RECORD>
<ROW>
<COLUMN SOURCE="STREET" NAME="STREET" xsi:type="SQLNVARCHAR"/>
</ROW>
</BCPFORMAT>
即使源数据只包含一些带有 1 个特殊字符的文本,最终结果如下所示:慊潫ⵢ瑓晥慦瑓慲鿃㐱
当使用 xsi:type="CharTerm"
而不是 xsi:type="NCharTerm"
时,结果如下所示: ...-Straßs
...
我是不是做错了什么,或者 XML 格式文件没有正确实现 UTF-8 支持?
将终结符更改为 TERMINATOR="\r[=10=]\n[=10=]"
。使用 NCharTerm 时,您必须考虑额外的字节数。
在尝试了这个之后,我找到了解决方案。
备注
- 无论有没有 BOM 表头,这都适用。这无关紧要。
- 罪魁祸首使用了 XML 文件中的 COLLATION 参数。省略它解决了编码问题。我对为什么会这样有直觉,但也许有更多见识的人可以在评论中解释...
DATAFILETYPE = 'char'
选项似乎没有必要。- 在XML文件中,字段的
xsi:type
需要是CharTerm,不是NCharTerm。 - 这适用于 \r\n、\n 或 \r。只要您正确设置了 TERMINATOR,它就可以工作。不需要 \n[=55=] 变化(这甚至会破坏功能,因为这不是 UTF-16 或 UCS-2)。
您可以在下方找到便于重复使用的概念验证...
data.txt
ß
ß
ß
Table
CREATE TABLE [dbo].[TEST](
TEST [nvarchar](500) NULL
)
formatfile.xml
<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<FIELD ID="1" xsi:type="CharTerm" TERMINATOR="\r\n" MAX_LENGTH="20"/>
</RECORD>
<ROW>
<COLUMN SOURCE="1" NAME="TEST" xsi:type="SQLNVARCHAR"/>
</ROW>
</BCPFORMAT>
批量插入
bulk insert TEST..TEST
from 'data.txt'
with (formatfile = 'formatfile.xml', CODEPAGE = 65001)