1.字符集说明
ORACLE数据库字符集包括两部分:数据库字符集和客户端字符集.
查看数据库字符集:
SQL> select * from nls_database_parameters a where a.PARAMETER in ('NLS_LANGUAGE','NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET','NLS_TERRITORY');
PARAMETER VALUE
------------------------------ --------------------------------------------------------------------------------
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CHARACTERSET ZHS16GBK
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_LANGUAGE:数据库使用的语言,影响 返回消息的语言、日期类型等,影响NLS_DATE_LANGUAGE 和NLS_SORT.
NLS_CHARACTERSET:数据库使用的字符集
NLS_NCHAR_CHARACTERSET:国家字符集
NLS_TERRITORY :数据库的区域,影响NLS_DATE_FORMATE等
客户端的字符集
客户端指SQLPLUS等工具,这些工具所在的系统也有自己的字符集。windows下查看字符集:
C:\Users\wj>chcp
活动代码页: 936
936代表 简体中文,相当于数据中的zhs16gbk。客户端中字符集设置是在注册表中ORACLEHOME中的NLS_LANG。可以命令台中设置字符集和语言,格式为 set nls_lang= <LANGUAGE>_<TERRITORY>.<CHARACTERSET>,如:
set nls_lang=SIMPLIFIED CHINESE_CHINA.ZHS16GBK,只对当前窗口有效。
注意:实际上并不会改变OS的字符集,只是设置ORACLE的环境变量
2.数据库与客户端之间的字符集转换的问题
有时候会经常发现乱码。原因就是客户端和数据库之间进行字符集转换,导致字符丢失出现乱码。
如:
服务器的字符集是WB8ISO8859P1,这是个单字节的字符集。
现在设置客户端的字符集:set nls_lang=.ZHS16GBK,然后向表T中加入一行数据
insert into t values('ZHS16GBK','我们');
commit;
再设置客户端的字符集:set nls_lang=. WB8ISO8859P1,然后再向表T中加入一行数据
insert into t values('WB8ISO8859P1','我们');
commit;
然后分别设置字符集检查T表:
发现客户端字符集为WB8ISO8859P1查询时,第一次条件显示乱码,本来是"我们"显示为"靠",第二条显示正常。
客户端字符集为ZHS16GBK时,两条记录都是乱码。
来分析下原因.
假设"我们"的ZHS16GBK编码为9922 0034.客户端实际发送的是ZHS16GBK编码.
客户端字符集设置为ZHS16GBK时,写到数据库时,由于NLS_LANG和数据库里的不一样,要发生转换,这时将会吧9922 0034 转换为WB8ISO8859P1里的编码,而WB8ISO8859P1没有表示"我们"的编码,会用一个默认的字符代替,假设是034 234,这时保存的字符已经不是"我们"。当查询时,会把034 234 转换到ZHS16GBK,这里显示为"靠".其实就是在ZHS16GBK-> WB8ISO8859P1丢失了字符.
客户端字符集设置为WB8ISO8859P1时,写到数据库时,由于NLS_LANG和数据库里的一样,不用发生字符转换,直接把9922 0034存到数据库中(虽然9922 0034在WB8ISO8859P1中不一定是有意义的编码,但是可以这样存储).在查询的时候,也不用发生字符转换,直接把9922 0034 返回给客户端,客户端通过ZHS16GBK解释9922 0034为"我们".
参考引用:《韩思捷:教你如何成为10G OCP》