在PUB上看到一个网友问起,一个字符集问题,大概意思是说,在客户端添加了一个中文字符,然后在数据库查询,发现变成了??,忍不住,自己测试了以下!
操作是远程登陆到了服务器上进行的。
首先设置oracle的环境变量中客户端字符集
NLS_LANG="simplified chinese"_china.zhs16gbk
服务器端字符集为AU32UTF8
测试开始:
[oracle@www ~]$ sqlplus "/as sysdba"
SQL*Plus: Release 9.2.0.8.0 - Production on 星期三 10月 25 10:12:46 2006
www.ixdba.net
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
SQL> insert into test values('煊');
1 row created.
SQL> select * from test;
A
--------------------
煊
SQL> commit;
Commit complete.
SQL> quit
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
可以正常显示,因为NLS_LANG设置字符集是服务器端的子集,所以肯定能够显示。
继续测试,
在oracle的.bash_profile去掉NLS_LANG="simplified chinese"_china.zhs16gbk
然后继续:
[oracle@www ~]$ sqlplus "/as sysdba"
SQL*Plus: Release 9.2.0.8.0 - Production on Wed Oct 25 10:14:44 2006
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
SQL> insert into test values('煊');
1 row created.
SQL> select * from test;
A
----------
?
??
SQL>
可以看到,不能显示了
那么是不是更改oracle的.bash_profile添加
NLS_LANG="simplified chinese"_china.zhs16gbk就可以了?
继续测试:
[oracle@www ~]$ sqlplus "/as sysdba"
SQL*Plus: Release 9.2.0.8.0 - Production on 星期三 10月 25 10:45:10 2006
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
SQL> select * from test;
A
--------------------
煊
??
可以看到,仍然是"??",怎么回事呢!
总结:
其实oracle在插入数据的时候,首先检查客户端的字符集,上面输入中文字符的时候,虽然插入时刻能显示中文,这只是操作系统支持中文的原因,在插入数据时,oracle会检查客户端,也就是sqlplus端字符集设置,插入的是中文,但是客户端设置是默认英文的,两者不同,要发生第一次字符集转换,但是由于插入的中文字符在客户端字符集中没有能够显示这个中文字符的信息,所以用一个"??"统一表示了。
接下来,还有第二次的字符转换,就是客户端到服务器端的字符集转换,由于插入的中文字符到数据中已经是"??"了,而这个字符转换到服务器端数据库的字符集AU32UTF8,仍然是"??"所以就把这个"??"存储到了数据库中,因此这样存储以后,无论如何设置客户端的字符集,都是不管用的,因为数据库中存储的就是"??"!