环境:
操作系统字符集
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
SQL> select * from database_properties;
NLS_CHARACTERSET WE8ISO8859P1
测试一:
1、创建测试表
SQL> create table test (text varchar2(50));
表已创建。
2、插入数据并查看(客户机NLS_LANG与服务器NLG_LANG不一致)
SQL> insert into test values('上海大学');
已创建 1 行。
SQL> select t.*, dump(text,1016) dump from test t;
TEXT DUMP
---------- ----------------------------------------------------------
???? Typ=1 Len=4 CharacterSet=WE8ISO8859P1: bf,bf,bf,bf
分析:
1)没有设置NLS_LANG时,客户机采用系统字符集
因为没有指定NLS_LANG在客户机,所以采用的是系统的NLS_LANG,即 ZHS16GBK字符集。
2)当插入数据时,如果客户机NLS_LANG与服务器NLS_LANG不一致时,需要进行编码转化,
因为转换后的字符集不是转换前字符集的超集,所以会出现不能表示转换前字符的含义的情况
当将‘上海大学’插入数据库时,数据库发现客户机的NLS_LANG与数据库服务器NLS_LANG不一致,于是将 ZHS16GBK表示的'上海大学'二进制编码转换为WE8ISO8859P1对应的二进制编码,
又因为WE8ISO8859P1无法有效表示‘上海大学,而将其转换为????,其二进制编码为bf,bf,bf,bf,即将4个字符的‘上海大学’转换为了4个字节的'????'值,并存入数据库。
3)当查看数据时,如果客户机NLS_LANG与服务器NLS_LANG不一致时,
需要进行编码转化,因为转换后的字符集是转换前字符集的超集,所以能正确表示转换前字符的含义
当查看时,同样发现NLS_LANG不一致,于是将4字节的WE8ISO8859P1值????转换为 ZHS16GBK表示的4个字符????,即8个字节
3、修改客户机NLS_LANG,并再次查询
(客户机NLS_LANG与服务器NLG_LANG一致)
E:\Documents and Settings\Administrator>set NLS_LANG=.WE8ISO8859P1
SQL> select t.*, dump(text,1016) dump from test t;
TEXT DUMP
---------- ------------------------------------------------------
靠靠 Typ=1 Len=4 CharacterSet=WE8ISO8859P1: bf,bf,bf,bf
分析:
因为将客户机的NLS_LANG成与服务器的NLS_LANG的字符集一致,所以当返回查询结果时,不进行字符集的转换,即将WE8ISO8859P1的????对应的二进制bf,bf,bf,bf用系统字符集 ZHS16GBK的方式进行编码读取,即2个字节表示一个字符,故是4个字节,对应 ZHS16GBK的2个字符。
注意:
是读取而不是转换后读取,如????4个字节用ZHS16GBK读取为‘靠靠’;????4个字节转换为ZHS16GBK后,变为8个字节,4个字符的????,再读取。
总结:
1)当在对一个数据库服务器进行操作时,请确保客户机的NLS_LANG字符集与客户机系统字符集一致,这样可以在其与数据库服务器字符集不一致时,进行编码转换。
2)当在对一个数据库服务器进行写入操作时,客户机系统的字符集应最好为服务器字符集的子集,或输入数据库的字符数据库字符集包含的,这样不会出现服务器无法转换的字符的情况。
3)当在对一个数据库服务器进行读取操作时,客户机系统的字符集应最好为服务器字符集的超集,或数据库输出的字符数据被客户机字符集所包含,这样不会出现客户机无法转换的字符的情况。
参考文献:
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24104518/viewspace-713833/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/24104518/viewspace-713833/