分享

字符集异常解决方案

 cinnamon 2011-10-07

问题一:不同字符集的数据库间的数据迁移.

两个数据库字符集不一样,现在要进行数据迁移,怎么办?
01数据库,字符集为AMERICAN_AMERICA.AL32UTF8
02数据库,字符集为AMERICAN_AMERICA.WE8ISO8859P1
现在要把01数据库里面的数据迁移到02数据库里面,但字符集不一样,该怎么解决呢???

解决方案:
建议你02库的字符集AL32UTF8一样。不过你需要注意你客户端的你字符集环境变量的设置,一般设置成zhs16gbk为好,如果设置成al32utf8有可能会显示乱码。

 

问题二: 数据库服务器与客户端的字符集都为us7ascII(只支持英文),但插入的是中文.正常显示,但有隐患!

设置客户端字符集为US7ASCII :
D:\>SET NLS_LANG=AMERICAN_AMERICA.US7ASCII
SQL> SELECT * FROM NLS_DATABASE_PARAMETERS;
PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_CHARACTERSET               US7ASCII

//由上可得,查看服务器字符集为US7ASCII

    建立测试表
SQL> CREATE TABLE TEST (R1 VARCHAR2(10));

Table created.

    插入数据
SQL> INSERT INTO TEST VALUES('东北');

1 row created.

SQL> SELECT * FROM TEST;

R1
----------
东北

SQL> EXIT


--------------------------------------------------------------------------------
这一部分的实验数据的存取与显示都正确,好象没什么问题,但实际上却隐藏着很大的隐患。
首先,要将汉字存入数据库,而将数据库字符集设置为US7ASCII是不合适的。US7ASCII字符集只定义了128个符号,并不支持汉字。另外,由于在SQL*PLUS中能够输入中文,操作系统缺省应该是支持中文的,但在NLS_LANG中的字符集设置为US7ASCII,显然也是不正确的,它没有反映客户端的实际情况。
但实际显示却是正确的,这主要是因为Oracle检查数据库与客户端的字符集设置是同样的,那么数据在客户与数据库之间的存取过程中将不发生任何转换。具体地说,在客户端输入“东北”,“东”的汉字的编码为182(10110110)、171(10101011),“北”汉字的编码为177(10110001)、177(10110001),它们将不做任何变化的存入数据库中,但是这实际上导致了数据库标识的字符集与实际存入的内容是不相符的,从某种意义上讲,这也是一种不一致性,也是一种错误。而在SELECT的过程中,Oracle同样检查发现数据库与客户端的字符集设置是相同的,所以它也将存入的内容原封不动地传送到客户端,而客户端操作系统识别出这是汉字编码所以能够正确显示。

在这个例子中,数据库与客户端的设置都有问题,但却好象起到了“负负得正”的效果,从应用的角度看倒好象没问题。但这里面却存在着极大的隐患,比如在应用length或substr等字符串函数时,就可能得到意外的结果。另外,如果遇到导入/导出(import /export)将会遇到更大的麻烦。

 

问题三:服务器与客户端是us7ascii,而插入中文后. 再修改客户端为ZHS16GBK,无法正常显示!

接着问题二的内容与操作,然后:

更改客户端字符集为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”。

 

问题四:服务器是us7ascii,客户端字符集设置为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个)。

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多