Oracle数据库字符集分析之一

环境:

操作系统字符集
SIMPLIFIED CHINESE_CHINA.ZHS16GBK

test实例字符集:
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)当在对一个数据库服务器进行读取操作时,客户机系统的字符集应最好为服务器字符集的超集,或数据库输出的字符数据被客户机字符集所包含,这样不会出现客户机无法转换的字符的情况。

参考文献:
http://space.itpub.net/519536/viewspace-626952
请使用浏览器的分享功能分享到微信等