从 CSV 文件导入的字符转换问题

Raf*_*ima 3 sql-server etl collation import encoding

加载 CSV 文件后,有各种单词错误地“写入”到数据库中。

一些例子:

  • Diã¡ria 应该 Diária
  • Crã©dito 应该 Crédito
  • Ligaã§ãµes 应该 Ligações
  • Usuã¡rio 应该 Usuário
  • Nãºmeros 应该 Números

有没有办法将符号转换为正确的字符?

我已经做了多次测试不同collations,并functions可能在互联网上搜索,但没有成功。

Sol*_*zky 5

有各种单词被错误地“写入”到数据库中。

不,字符被错误地读取。他们写得正确。或者,另一种看待这个问题的方法是:字符被错误地写入数据文件. 无论哪种方式,SQL Server 都在做它被要求做的事情。

这是一个简单的编码问题。数据最初以 UTF-8 格式导出,但随后该 UTF-8 编码文件被读入 SQL Server,就好像它是使用代码页 1252 的扩展 ASCII 文件一样。 有三个线索表明这是问题所在:

  1. 大多数字符都能正确通过。那些不是重音字符。
  2. 不正确的字符作为两个字符而不是一个字符出现。
  3. 您提到导出到“ASCII”文件有效。

UTF-8 是一种多字节编码:它根据被编码的字符使用不同数量的字节。包含美国英语字母表的前 128 个代码点 (U+0000 - U+007F) 均使用 1 个字节。高于该范围的代码点占用 2 - 4 个字节。这就是为什么预期系统之间传递的一些特点:N(大写拉丁字母“N”)是0x4E在UTF-8,以及在代码页1252(事实上,它的0x4E在所有8位代码页支持的SQL Server )。这也是 UTF-8 如此流行的原因之一。但是,在 UTF-8 中,重音字符不是 1 个字节:

  • á(U + 00E1)被编码为以UTF-8的两个字节:0xC30xA1。当这两个字节被期望代码页 1252 的东西读取时,它们被解释为Ã(代码页 1252 上的0xC3)和¡(代码页 1252 上的0xA1)。然后,无论是您还是您的导入过程,都将小写Ã(可能是因为它位于单词的中间),这就是您最终得到的结果:Usuã¡rio

  • ú(U + 00FA)被编码为以UTF-8的两个字节:0xC30xBA。当这两个字节被期望代码页 1252 的东西读取时,它们被解释为Ã(代码页 1252 上的0xC3)和º(代码页 1252 上的0xBA)。然后,无论是您还是您的导入过程,都将小写Ã(可能是因为它位于单词的中间),这就是您最终得到的结果:Nãºmero

您的选择是:

  1. 使用代码页 1252(在导出时)将文件编码为(扩展)ASCII,并且不要更改它被读入 SQL Server 的方式。(听起来你已经这样做了)。

  2. 继续使用 UTF-8 编码导出文件,但通过将文件编码为 UTF-8 来更改文件被读入 SQL Server 的方式。请注意,对于使用BCP.exeBULK INSERT、 或 的任何人OPENROWSET(BULK...),此选项仅从 SQL Server 2016 开始可用。要使用的代码页是65001(通常表示带有字节顺序标记的UTF-8 ,但我不确定 SQL Server在这些情况下需要字节顺序标记)。