【问题标题】:DB2 UTF-8 Data Storage - Extraneous Byte ValuesDB2 UTF-8 数据存储 - 无关字节值
【发布时间】:2014-07-12 18:32:27
【问题描述】:

我正在尝试将 Unicode 字符以 UTF8 格式存储在 DB2 数据库中。我已经确认字符集是 1208 并且数据库被指定为保存 UTF8。

然而,在查询一些 unicode 数据时,我得到了奇怪的结果。

select hex(firstname), firstname, from my_schema.my_table where my_pk = 1234;

结果如下:

C383C289    Ã

结果中的字符显示错误。据我所知,它由十六进制值“C383C289”表示。插入时发送的实际字符是 É,应在 UTF8 中表示为 C389。

在这个阶段,我假设它可能是我用来查询数据的程序解释错误。但是十六进制值(第一个结果列)在多大程度上是错误的?它们似乎在实际字节之间有未使用的绒毛“83C2”。或者,“C383C289”实际上是正确的,一些 UTF8 解码引擎无法处理绒毛?这在我看来不太可能。

客户端(DB2 For Toad 和 WinSQL)都将字符显示为 Ã,在 UTF8 中表示为 C383。

*编辑。我在 CLI 上进行了测试,它正确地返回了 É 字符。我错过了什么吗? “十六进制”函数是否返回了不应该返回的内容?

【问题讨论】:

  • 看起来您的插入过程以某种方式搞砸了。如果它正确存储“É”,十六进制值将是 C383。
  • @mustaccio C383 是 A,而不是 E。注意,我刚刚从 DB2 CLI 测试过,它似乎以某种方式返回了 E。
  • 您的 DB2 服务器在什么平台上? IBM i 和 z/OS 是 EBCDIC 机器,而不是基于 ASCII 的机器。对各种字符集的支持取决于平台。
  • @WarrenT 它在 IBM AIX 机器上。盒子上的文件和 ssh 会话可以很好地处理 utf8 编码,在这方面我们没有遇到任何问题。

标签: unicode utf-8 db2 hex


【解决方案1】:

É (U+00C9) 在 UTF-8 中是 0xC3 0x89

à (U+00C3) 在 UTF-8 中是 0xC3 0x83

(U+0089) 在 UTF-8 中是 0xC2 0x89

这意味着您的插入代码采用É,将其编码为UTF-8 八位字节0xC3 0x89,然后将这些八位字节插入数据库。数据库将它们解释为单独的字符 0xC30x89 并将它们第二次编码为 UTF-8,从而生成 0xC3 0x83 0xC2 0x89

您需要修复插入代码以不再执行初始编码,因此数据库将按原样查看原始 É 而不是它的预编码版本。任何人都可以猜测您实际上是如何做到的,因为您还没有显示您的实际插入代码。

【讨论】:

  • 谢谢,这就是导致问题的原因。具有讽刺意味的是,当 DB 是 latin-1 编码时,它曾经可以正常工作,而这个问题只有在我们切换到 UTF8 时才出现。
  • 正确,因为 Latin-1 对大多数 Unicode 代码点按原样进行编码,直至并包括 U+00FF。例如,Latin-1 中的É (U+00C9) 是0xC9。所以数据库似乎正在准确地保存你给它的东西。
【解决方案2】:

这并不是真正的答案,只是为了展示正确的行为:

> db2 "insert into t1 values ('Élan')"
DB20000I  The SQL command completed successfully.
> db2 select "hex (f1), f1 from t1"

1          F1   
---------- -----
C3896C616E Élan 

  1 record(s) selected.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-22
    • 1970-01-01
    相关资源
    最近更新 更多