由此可以得出结论为:若数据库的字符集是ZHS16GBK, 那么Oracle会根据内部的MAP,按UTF8截取客户端发来的字符串, 转换成ZHS16GBK,因此显示的结果是正常的,但是存入的数据编码却变了。
实验 2.
~~~~~~~~~~~~~
a) 设置个人工具的字符集为 GB2312
b) 设置NLS_LANG=american_america.AL32UTF8
[oracle@hxy ~]$ export NLS_LANG=american_america.AL32UTF8
[oracle@hxy ~]$ sqlplus / as sysdba
SQL*Plus: Release 10.2.0.1.0 - Production on Wed Mar 26 10:57:12 2014
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options
SQL> desc t2
Name Null Type
----------------------------------------- -------- ----------------------------
NLS_LANG VARCHAR2(20)
INPUT_CHARSET VARCHAR2(20)
C1 VARCHAR2(20)
SQL> insert into t2 values('UTF8','ZHS16GBK','中国' );
SQL> select c1,dump(c1,16) from t2;
SQL> insert into t2 values('UTF8','ZHS16GBK,'中国' );
SQL> commit;
Commit complete.
SQL> select * from t2;
NLS_LANG INPUT_CHARSET C1
------------------------------------------------------------ ---------------------------------- -------------------------- ------------------------------------------------------------
UTF8 ZHS16GBK 锛
ZHS16GBK ZHS16GBK 涓?
ZHS16GBK UTF8 娑 娴
全部变成乱码了。
SQL> select c1, input_charset,dump(c1,16) from t2;
C1 INPUT_CHARSET DUMP(C1,16)
----------------------------------- ------------------------------------------------------------ ----------------------------------------------------
锛 ZHS16GBK Typ=1 Len=4: a3,bf,3f,3f
涓? ZHS16GBK Typ=1 Len=4: d6,d0,b9,fa
娑 娴 UTF8 Typ=1 Len=6: e4,b8,ad,e5,9b,bd
上面标黄色的编码明显是错误的,这种情况叫garbage-in--garbage-out, 这是最有欺骗性的一种设置.
将个人工具的字符集修改回与NLS_LANG相同的设置---UTF8就会出现问题.
SQL> select c1, input_charset,dump(c1,16) from t2;
C1 INPUT_CHARSET DUMP(C1,16)
---------------------------------------- --------------------------------- ----------------------------------------------------------
? <<=== ZHS16GBK Typ=1 Len=4: a3,bf,3f,3f
中国 ZHS16GBK Typ=1 Len=4: d6,d0,b9,fa
涓? UTF8 Typ=1 Len=6: e4,b8,ad,e5,9b,bd
此编码是不能显示正常,出现了乱码行为,这就是一种欺骗性的,日常工作中经常容易发生,但是很难发现问题,这个一定要小心。
实验 3.
个人工具: UTF8
NLS_LANG: american_america.UTF8
SQL>insert into t2 values('UTF8','UTF8','中国');
SQL> set line 200
SQL> select c1, input_charset,dump(c1,16) from t2;
C1 INPUT_CHARSET DUMP(C1,16)
----------------------------------- ------------------------------- --------------------------------------------
? ZHS16GBK Typ=1 Len=4: a3,bf,3f,3f
中国 UTF8 Typ=1 Len=4: d6,d0,b9,fa
中国 ZHS16GBK Typ=1 Len=4: d6,d0,b9,fa
涓? UTF8 Typ=1 Len=6: e4,b8,ad,e5,9b,bd
可以看到只要个人工具的字符集和nls_lang的字符集是是一致的,并且数据库字符集和客户端字符集可以相互转换就不会出现乱码,
不出现乱码并不是之前所说的客户端字符集并一定是和数据库字符集一致。
3. 关于export/import的字符集问题.
a) 导出时NLS_LANG的设置, 决定存地DMP文件中的字符集.
b) 导入时的字符集转换情况分三步:
b.1 读取DMP文件的字符集设置, 一般存在文件的2~3个字节. 10g以前, 可以通过更改这两个字节的值, 来修改字符集. 但是, 10G,11G以后, 字符集还存在于其它地方, 基本没有修改的可能.
b.2 将DMP文件里的字符转换成, import时NLS_LANG所设置的字符集.
b.3 导入时, 将字符从 NLS_LANG转为数据库字集.
$ export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
$ exp \"/ as sysdba\" file=demo.dmp tables=t2;
Export: Release 11.2.0.4.0 - Production on Sun Mar 23 19:50:24 2014
Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing opt