【问题标题】:Issues with latin chars encoding in Oracle tableOracle 表中的拉丁字符编码问题
【发布时间】:2018-11-20 06:55:31
【问题描述】:

我有一个带有

的 oracle 数据库
NLS_CHARACTERSET=AL32UTF8  

sqlplus nls_lang is WE8ISO8859P1

unix shell 也是 iso

varchar2 列有字母:LATIN SMALL LETTER O WITH ACUTE

当我在此列上调用 DUMP 函数时,我得到:

Typ=1 Len=4: 195,131,194,179

这看起来不像 UTF8。

运行 SELECT 会在屏幕上显示损坏的 cha。

运行 CONVERT(VALUE, 'WE8ISO8859P1', 'UTF8') - 显示正确的值,但编码看起来不像 UTF8...


如果我尝试手动插入相同的字母,则选择查询会返回正确的字符。

转储显示 195,179,这是正确的 UTF8 代码。

运行 CONVERT(VALUE, 'WE8ISO8859P1', 'UTF8') - 失败
ORA-29275: 部分多字节字符

这很奇怪,因为 195,179 确实是 UTF8。

请向我澄清以上内容。

【问题讨论】:

  • 你从DUMP(..., 1016)得到什么?
  • CONVERT(VALUE, 'UTF8', 'WE8ISO8859P1') 是错误的,即这意味着“Convert from WE8ISO8859P1 to UTF8” - 但是,您的值已经是 UTF -8 根据NLS_CHARACTERSET
  • 对于已经存在的值,我得到:Typ=1 Len=4 CharacterSet=AL32UTF8: c3,83,c2,b3 对于我插入的新值,我得到:Typ=1 Len=2 CharacterSet= AL32UTF8: c3,b3
  • 对不起,我粘贴了错误的转换,我使用的原件是CONVERT(VALUE,'WE8ISO8859P1','UTF8'),之后我做了一些测试所以我换了地方......我将更新问题
  • 您使用哪个客户端插入和查询数据?

标签: oracle character-encoding char


【解决方案1】:

Typ=1 Len=4 CharacterSet=AL32UTF8: c3,83,c2,b3 显然插入错误。

当客户端以 UTF-8 发送字符但数据库将此数据视为 WE8ISO8859P1 时发生这种情况。

如果客户端以 UTF-8 格式发送数据,那么您还必须设置 NLS_LANG=.AL32UTF8(语言和地区是可选的,此处不相关)。

但是,当您运行 sqlplus 时,sqlplus 会从命令行继承字符集,这似乎是 ISO 8859-1。所以在你启动sqlplus之前你必须运行export NLS_LANG=.WE8ISO8859P1才能正确设置它。

我用你的数据创建一个表格:

SELECT 
    val, 
    DUMP(val, 1016) as dump_val, 
    DUMP(CONVERT(VAL, 'WE8ISO8859P1'), 1016) as conv_dump
FROM AA;


+-------------------------------------------------------------------------------------------+
|VAL|DUMP_VAL                                      |CONV_DUMP                               |
+-------------------------------------------------------------------------------------------+
|ó |Typ=1 Len=4 CharacterSet=AL32UTF8: c3,83,c2,b3|Typ=1 Len=2 CharacterSet=AL32UTF8: c3,b3|
|ó  |Typ=1 Len=2 CharacterSet=AL32UTF8: c3,b3      |Typ=1 Len=1 CharacterSet=AL32UTF8: f3   |
+-------------------------------------------------------------------------------------------+

第 1 行显示损坏的数据,第 2 行正常。

CONVERT(VAL, 'WE8ISO8859P1') 用于将损坏的数据转换为正确的字符集,因此CONVERT(UTL_RAW.CAST_TO_VARCHAR2('C383C2B3'), 'WE8ISO8859P1') 的转换是可以的。

但是,CONVERT(UTL_RAW.CAST_TO_VARCHAR2('C3B3'), 'WE8ISO8859P1') 会返回十六进制 F3,这不是有效的 UTF-8 字节序列,因此您会得到 ORA-29275。

【讨论】:

  • 仍然不清楚,'数据库将此数据视为 WE8ISO8859P1' 但 NLS_CHARACTERSET=AL32UTF8。 c3,83,c2,b3 '显然是错误的',但为什么隐蔽工作对此有效,而对真正的 UTF8 的 195,179 无效?
  • 是的,但是当“对于已经存在的价值”被插入时(可能是其他人),那么 NLS_LANG 设置错误。
  • 是的,这是真的!它与其他一些 NLS_LANG 一起插入(不知道是哪个)。为什么我手动插入的数据看起来像 UTF8 编码 195,179 ,为什么转换功能不起作用,为什么它对 195,131,194,179 起作用?
  • 关于您的更新,'c3,b3' 是 UTF-8 编码,为什么 CONVERT 会失败,我需要了解这部分。 C383C2B3 - 甚至不是 UTF8,不知道是什么。
  • Convert 主要用于纠正损坏的数据(这是人们应该使用它的唯一原因)。但是“C3B3”没有损坏,没有什么需要纠正的。
猜你喜欢
  • 2017-09-24
  • 2011-01-27
  • 1970-01-01
  • 2021-03-19
  • 2013-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多