oracle字符集理解(2)

发表于:2013-12-30来源:IT博客大学习作者:rethink点击数: 标签:oracle
Language:显示oracle消息,校验,日期命名 Territory:指定默认日期、数字、货币等格式 Client character set:指定客户端将使用的字符集 例如:NLS_LANG=AMERICAN_AMERI

  Language:显示oracle消息,校验,日期命名

  Territory:指定默认日期、数字、货币等格式

  Client character set:指定客户端将使用的字符集

  例如:NLS_LANG=AMERICAN_AMERICA.US7ASCII

  AMERICAN是语言,AMERICA是地区,US7ASCII是客户端字符集

  2.5.3客户端字符集设置方法

  1)UNIX环境

  $NLS_LANG=“simplified chinese”_china.zhs16gbk

  $export NLS_LANG

  编辑oracle用户的profile文件

  2)Windows环境

  编辑注册表

  Regedit.exe---HKEY_LOCAL_MACHINE---SOFTWARE---ORACLE―HOME0

  2.5.4 NLS参数查询

  Oracle提供若干NLS参数定制数据库和用户机以适应本地格式,例如有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等,可以通过查询以下数据字典或v$视图查看。

  NLS_DATABASE_PARAMETERS--显示数据库当前NLS参数取值,包括数据库字符集取值

  NLS_SESSION_PARAMETERS--显示由NLS_LANG 设置的参数,或经过alter session 改变后的参数值(不包括由NLS_LANG 设置的客户端字符集)

  NLS_INSTANCE_PARAMETE--显示由参数文件init.ora 定义的参数V$NLS_PARAMETERS--显示数据库当前NLS参数取值

  2.5.5修改NLS参数

  使用下列方法可以修改NLS参数

  (1)修改实例启动时使用的初始化参数文件

  (2)修改环境变量NLS_LANG

  (3)使用ALTER SESSION语句,在oracle会话中修改

  (4)使用某些SQL函数

  NLS作用优先级别:Sql function>alter session>环境变量或注册表>参数文件>数据库默认参数

  三.导入/导出与字符集转换

  3.1 EXP/IMP

  Export 和 Import 是一对读写Oracle数据的工具。Export 将 Oracle 数据库中的数据输出到操作系统文件中, Import 把这些文件中的数据读到Oracle 数据库中,由于使用exp/imp进行数据迁移时,数据从源数据库到目标数据库的过程中有四个环节涉及到字符集,如果这四个环节的字符集不一致,将会发生字符集转换。

  EXP

  IMP

  四个字符集是

  (1)源数据库字符集

  (2)Export过程中用户会话字符集(通过NLS_LANG设定)

  (3)Import过程中用户会话字符集(通过NLS_LANG设定)

  (4)目标数据库字符集

  3.2导出的转换过程

  在Export过程中,如果源数据库字符集与Export用户会话字符集不一致,会发生字符集转换,并在导出文件的头部几个字节中存储Export用户会话字符集的ID号。在这个转换过程中可能发生数据的丢失。

  例: 如果源数据库使用ZHS16GBK,而Export用户会话字符集使用US7ASCII,由于ZHS16GBK是16位字符集,而US7ASCII是7位字符集,这个转换过程中,中文字符在US7ASCII中不能够找到对等的字符,所以所有中文字符都会丢失而变成“?? ”形式,这样转换后生成的Dmp文件已经发生了数据丢失。

  因此如果想正确导出源数据库数据,则Export过程中用户会话字符集应等于源数据库字符集或是源数据库字符集的超集

  3.2.1 修改dmp文件字符集

  上文说过,dmp文件的第2第3字节记录了字符集信息,因此直接修改dmp文件的第2第3字节的内容就可以‘骗’过oracle的检查。这样做理论上也仅是从子集到超集可以修改,但很多情况下在没有子集和超集关系的情况下也可以修改,我们常用的一些字符集,如 US7ASCII,WE8ISO8859P1,ZHS16CGB231280,ZHS16GBK基本都可以改。因为改的只是dmp文件,所以影响不大。

  具体的修改方法比较多,最简单的就是直接用UltraEdit修改dmp文件的第2和第3个字节。比如想将dmp文件的字符集改为ZHS16GBK,可以用以下SQL查出该种字符集对应的16进制代码:

  SQL> select to_char(nls_charset_id(\'ZHS16GBK\'), \'xxxx\') from dual;

  0354

  然后将dmp文件的2、3字节修改为0354即可。

  如果dmp文件很大,用ue无法打开,就需要用程序的方法了。网上有人用java存储过程写了转换的程序(用java存储过程的好处是通用性教好,缺点是比较麻烦)。我在windows下测试通过。但要求oracle数据库一定要安装JVM选项。有兴趣的朋友可以研究一下程序代码

  3.3导入的转换过程

  (1)确定导出数据库字符集环境

  通过读取导出文件头,可以获得导出文件的字符集设置

  (2)确定导入session的字符集,即导入Session使用的NLS_LANG环境变量

  (3)IMP读取导出文件

  读取导出文件字符集ID,和导入进程的NLS_LANG进行比较

  (4)如果导出文件字符集和导入Session字符集相同,那么在这一步骤内就不需要转换,如果不同,就需要把数据转换为导入Session使用的字符集。可以看出,导入数据到数据库过程中发生两次字符集转换

  第一次:导入文件字符集与导入Session使用的字符集之间的转换,如果这个转换过程不能正确完成,Import向目标数据库的导入过程也就不能完成。

  第二次:导入Session字符集与数据库字符集之间的转换。

  然而,oracle8i的这种转换只能在单字节字符集之间进行,oracle8i导入Session不支持多字节字符集之间的转换,因此为了避免第一次转换,导入Session使用的NLS_LANG与导出文件字符集相同,第二次转换(通过SQL*Net)支持任何两种字符集。以上情况在Oracle9i 中略有不同

  四.乱码问题

  oracle在数据存储、迁移过程中经常发生字符乱码问题,归根到底是由于字符集使用不当引起。下面以使用客户端sqlplus向数据库插入数据和导入/导出(EXP/IMP)过程为例,说明乱码产生的原因。

原文转自:http://blogread.cn/it/article/4654