oracleimpexp字符集问题
在做EXP/IMP操作时,会发⽣字符集转换。且发⽣多次,具体过程如下:
1、在EXP导出时,EXP会检查数据库字符集与本地NLS_LANG参数所指定的字符集是否⼀致,若不⼀致,则会发⽣字符转换,⽽字符转换过程中可能发⽣字符丢失。
举例来说,如果数据为AL32UTF8字符集,⽽本地电脑的NLS_LANG所指定的字符集是US7ASCII,那么所有英⽂,数字及标准符号以外的字符在这⼀步时,就已经丢失了。因为ASCII不⽀持这些字符以外的字符,⽐如中⽂字符。
2、在IMP导⼊时,先检查导出⽣成的DMP⽂件的字符集标志(如何查看后⾯再说)。再检查本地电脑的NLS_LANG的设置,若两者不⼀致,则发⽣字符集转换。
3、再检查⽬标数据库的字符集,若与本地电脑的NLS_LANG的设置也不⼀致,则再次发⽣字符集转换。
如果在以上发⽣字符集转换的可能点上,源字符集与⽬标字符集不⼀致,且不是⽬标字符集的⼦集,就会发⽣字符集的转换,且丢失那些在⽬标字符集中不存在的字符信息。
查看DMP⽂件字符集的⽅法:
dmp⽂件的第2和第3个字节记录了dmp⽂件的字符集。如果dmp⽂件不⼤,⽐如只有⼏M或⼏⼗M,可以⽤UltraEdit打开(16进制⽅式),看第2第3个字节的内容,如0354,然后⽤以下SQL查出它对应的字符集:
电脑主机打不开  SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;
  ZHS16GBK
  如果dmp⽂件很⼤,⽐如有2G以上(这也是最常见的情况),⽤⽂本编辑器打开很慢或者完全打不开,可以⽤以下命令(在unix主机上):
  cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6
  然后⽤上述SQL也可以得到它对应的字符集。
综上,若希望在EXP/IMP的全过程中,不发⽣字符丢失,就要把本地电脑上的NLS_LANG参数设置为与数据库相同的字符集。这样,在整个过程中,就没有字符集的转换,也就不会发⽣因字符转换⽽引发的字符丢失。但这样做的前提是⽬标数据库的字符集与源数据库的字符集⼀致。
若源数据库字符集与⽬标数据库字符集不⼀致,则分两种情况:
情况1:源数据库字符集是⽬标数据库的⼦集。则在导出时,在导出的电脑上设置NLS_LANG为源数据库字符集,这样导出时,不会发⽣字符集转换,同时导出的⽂件中,会标识该⽂件所使⽤的字符集为源数据库字符集。在导⼊时,在本地电脑上,设置NLS_LANG参数与DMP⽂件的字符集相同,这样,在导⼊的第⼀步时,也不会发⽣字符转换,只是在从会话向数据库中导⼊数据的过程中会发⽣字符转换,但由于源数据库字符集为⽬标库字符集的⼦集,所以,也不会发⽣因字符转换⽽发⽣的字符丢失或乱码现象。
情况2:源数据库字符集是⽬标数据库字符集的超集,或⼆者不兼容,那么字符丢失在所难免。除⾮源数据库中的字符恰好全部在⽬标库字符集中存在。⽐如源数据库字符集是zhs16gbk,但存储的全部是英⽂字符和数字,⽽没有任何中⽂或中⽂符号,那么,即使⽬标数据库的字符集是US7ASCII,也是不会出现字符丢失的。