oracle 字符集乱码本质验证(2)

发表于:2014-03-27来源:Csdn作者:蘑菇丁点击数: 标签:oracle
数据库中存储, 没有错, 但是iterm2将UTF8的码按照GB2312来解释, 并打在屏幕上, 明显编码长度是有问题的. 由此可以得出结论为:若数据库的字符集是ZHS16GBK,

  数据库中存储, 没有错, 但是iterm2将UTF8的码按照GB2312来解释, 并打在屏幕上, 明显编码长度是有问题的.

  由此可以得出结论为:若数据库的字符集是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 options

  Export done in ZHS16GBK character set and AL16UTF16 NCHAR character set

  server uses AL32UTF8 character set (possible charset conversion)

原文转自:http://blog.csdn.net/haoxiaoyan/article/details/22165465