如何在 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)