在Oracle上,我有一个字符串,以土耳其字符İ开头,这是Unicode字符0x0130“LATIN CAPITAL LETTER WITH DOT ABOVE”.这是在我的Unicode版本2.0书的打印副本.在UTF-8中,此字符为0xc4b0.
我们有很老的客户端应用程序,我们需要支持.他们会把这个文本发送给我们的“windows-1254”.我们以前只是闭上眼睛,把它存放起来,然后把它交回来.现在我们需要Unicode,或正在给予Unicode.
所以我有:
sql> select id,name from table where that thing; ID NAME ------ ------------------------ 746 Ý
这是有道理的,因为“İ”是Windows-1254中的0xdd,而在wondows-1252中的0xdd是“Ý”.我的终端可能设置为通常的Windows-1252.
但:
sql> select id,rawtohex(name) from table where that thing; ID RAWTOHEX(NAME) ------ ------------------------ 746 C39D
似乎没有相当于MysqL中的hex(name)函数.但是我一定会错过一些东西.我在这里缺少什么
我的java代码必须使用我提供的utf8,并保存一个utf8副本和一个Windows-1252副本. java代码给了我:
bytes (utf8): c4 b0 bytes (1254): dd
然而,当我保存它,客户端没有得到正确的字符.当我试图看看Oracle实际存储的时候,我得到了上面看到的垃圾.我不知道C39D来自哪里.有什么建议么?
我们将ojdbc14.jar内置到我们所有的应用程序中,我们正在连接到一个数据库,它表示它是“Oracle Database 11g企业版版本11.2.0.2.0 – 64位生产”.
dump
功能了解Oracle如何在内部存储数据.
您似乎对Oracle对待VARCHAR2字符设置转换的看法有误解:您不能影响Oracle如何物理存储数据. (如果还没有,请阅读:The Absolute Minimum Every Software Developer Absolutely,Positively Must Know About Unicode and Character Sets).
您的客户仅以二进制形式与Oracle通话.事实上,所有的系统只能用二进制交换信息.要了解彼此,两个系统都必须知道正在使用哪种语言(字符集).
在你的情况下,我们可以重建发生的事情:
>您的客户端将字节dd发送到Oracle,并说它是Windows-1252(而不是1254).
> Oracle查找其字符集表,并将该数据转换为此字符集中的符号..
> Oracle逻辑上将此信息存储在其表中.
>由于Oracle以UTF-8进行安装,因此将该数据转换为UTF-8二进制代码:
sql> SELECT rawtohex('Ý') FROM dual; RAWTOHEX('Ý') -------------- C39D
> Oracle在内部存储C39D.
您可以看到,问题来自于第一步:设置有问题.只要你不解决这个问题,系统将无法成功对话.
当您使用VARCHAR2时,转换是自动的,因为该数据类型是逻辑文本符号接口(您无法控制强制实际存储的二进制数据).