Oracle字符集问题总结(二)

2014-11-24 18:25:31 · 作者: · 浏览: 1
该没有问题;但出现问题的本质是我们让本应只存储英文字符的US7ASCII数据库,非常规地存储了中文信息,那么在转化过程中出现错误或麻烦就没什么奇怪的了,不出麻烦倒是有些奇怪了。
所以说要避免这种情况,就是要在建立数据库时选择合适的字符集,不让标签(数据库的字符集设置)与实际(数据库中实际存储的信息)不符的情况发生。

实验结果分析二
quote:
--------------------------------------------------------------------------------
[ 更改客户端字符集为ZHS16GBK
D:\>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
D:\>SQLPLUS "/ AS SYSDBA"
无法正常显示数据
SQL> SELECT * FROM TEST;
R1
--------------------
6+11
疑问1:ZHS16GBK为US7ASCII的超集,为什么在ZHS16GBK环境下无法正常显示
--------------------------------------------------------------------------------
这主要是因为Oracle检查发现数据库设置的字符集与客户端配置字符集不同,它将对数据进行字符集的转换。数据库中实际存放的数据为182(10110110)、171(10101011)、177(10110001)、177(10110001),由于数据库字符集设置为US7ASCII,它是一个7bit的字符集,存储在8bit的字节中,则Oracle忽略各字节的最高bit,则182(10110110)就变成了54(0110110),在ZHS16GBK中代表数字符号“6”(当然在其它字符集中也是“6”),同样过程也发生在其它3个字节,这样“东北”就变成了“6+11”。

实验结果分析三
quote:
--------------------------------------------------------------------------------
最初由 tellin 发布
用ZHS16GBK插入数据
SQL> INSERT INTO TEST VALUES('东北');
1 row created.
SQL> SELECT * FROM TEST;
R1
--------------------
6+11

SQL> EXIT
--------------------------------------------------------------------------------
当客户端字符集设置为ZHS16GBK后向数据库插入“东北”,Oracle检查发现数据库设置的字符集为US7ASCII与客户端不一致,需要进行转换,但字符集ZHS16GBK中的“东北”两字在US7ASCII中没有对应的字符,所以Oracle用统一的“替换字符”插入数据库,在这里为“?”,编码为63(00111111),这时,输入的信息实际上已经丢失,不管字符集设置如何改变(如下面引用的实验结果),第二行SELECT出来的结果也都是两个“?”号(注意是2个,而不是4个)。
quote:
--------------------------------------------------------------------------------
更改客户端字符集为US7ASCII
D:\>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII
D:\>SQLPLUS "/ AS SYSDBA"
无法显示用ZHS16GBK插入的字符集,但可以显示用US7ASCII插入的字符集
SQL> SELECT * FROM TEST;
R1
----------
东北


更改服务器字符集为ZHS16GBK
SQL> update props$ set value$='ZHS16GBK' WHERE NAME='NLS_CHARACTERSET';
1 row updated.
SQL> COMMIT;
更改客户端字符集为ZHS16GBK
D:\>SET NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
D:\>SQLPLUS "/ AS SYSDBA"
可以显示以前US7ASCII的字符集,但无法显示用ZHS16GBK插入的数据,说明用ZHS16GBK插入的数据为乱码。
SQL> SELECT * FROM TEST;
R1
--------------------
东北

--------------------------------------------------------------------------------
需要指出的是,通过“update props$ set value$='ZHS16GBK' WHERE NAME='NLS_CHARACTERSET';”来修改数据库字符集是非常规作法,很可能引起问题,在这里只是原文引用网友的实验结果。



实验结果分析四

quote:
--------------------------------------------------------------------------------
SQL> INSERT INTO TEST VALUES('东北');
1 row
created.


SQL> SELECT * FROM TEST;
R1
--------------------
东北

东北
SQL> EXIT
--------------------------------------------------------------------------------
由于此时数据库与客户端的字符集设置均为ZHS16GBK,所以不会发生字符集的转换,第一行与第三行数据显示正确,而第二行由于存储的数据就是63(00111111),所以显示的是“?”号。
quote:
--------------------------------------------------------------------------------
更改客户端字符集为US7ASCII
D:\>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII
D:\>SQLPLUS "/ AS SYSDBA"
无法显示数据
SQL> SELECT * FROM TEST;
R1
----------



疑问2:第一行数据是用US7ASCII环境插入的,为何无法正常显示?
--------------------------------------------------------------------------------
将客户端字符集设置改为US7ASCII后进行SELECT,Oracle检查发现数据库设置的字符集为ZHS16GBK,数据需要进行字符集转换,而第一行与第三行的汉字“东”与“北”在客户端字符集US7ASCII中没有对应字符,所以转换为“替换字符”(“?”),而第二行数据在数据库中存的本来就是两个“?”号,所以虽然在客户端显示的三行都是两个“?”号,但在数据库中存储的内容却是不同的。

实验结果分析五
quote:
-------------------------------------------