《字符集与oracle》由会员分享,可在线阅读,更多相关《字符集与oracle(12页珍藏版)》请在金锄头文库上搜索。
1、字符集与字符集与 ORACLEORACLE3.1 EXP/IMPExport 和 Import 是一对读写 Oracle 数据的工具。Export 将 Oracle 数据库中的数据输出到操作系统文件中, Import 把这些文件中的数据读到 Oracle 数据库中,由于使用 exp/imp 进行数据迁移时,数据从源数据库到目标数据库的过程中有四个环节涉及到字符集,如果这四个环节的字符集不一致,将会发生字符集转换。 EXP_ _ _|imp 导入文件|环境变量 NLS_LANG|-|数据库字符集|- - - 四个字符集是(1)源数据库字符集 (2)Export 过程中用户会话字符集(通过 NLS
2、_LANG 设定)(3)Import 过程中用户会话字符集(通过 NLS_LANG 设定)(4)目标数据库字符集 3.2 导出的转换过程在 Export 过程中,如果源数据库字符集与 Export 用户会话字符集不一致,会发生字符集转换,并在导出文件的头部几个字节中存储 Export 用户会话字符集的 ID 号。在这个转换过程中可能发生数据的丢失。例:如果源数据库使用 ZHS16GBK,而 Export 用户会话字符集使用US7ASCII,由于 ZHS16GBK 是 16 位字符集,而 US7ASCII 是 7 位字符集,这个转换过程中,中文字符在 US7ASCII 中不能够找到对等的字符,所
3、以所有中文字符都会丢失而变成“? ”形式,这样转换后生成的 Dmp 文件已经发生了数据丢失。因此如果想正确导出源数据库数据,则 Export 过程中用户会话字符集应等于源数据库字符集或是源数据库字符集的超集 3.3 导入的转换过程(1)确定导出数据库字符集环境通过读取导出文件头,可以获得导出文件的字符集设置(2)确定导入 session 的字符集,即导入 Session 使用的NLS_LANG 环境变量(3)IMP 读取导出文件读取导出文件字符集 ID,和导入进程的 NLS_LANG 进行比较(4)如果导出文件字符集和导入 Session 字符集相同,那么在这一步骤内就不需要转换, 如果不同,
4、就需要把数据转换为导入 Session 使用的字符集。可以看出,导入数据到数据库过程中发生两次字符集转换第一次:导入文件字符集与导入 Session 使用的字符集之间的转换,如果这个转换过程不能正确完成,Import 向目标数据库的导入过程也就不能完成。第二次:导入 Session 字符集与数据库字符集之间的转换。四. 查看数据库字符集涉及三方面的字符集,1. oracel server 端的字符集;2. oracle client 端的字符集;3. dmp 文件的字符集。在做数据导入的时候,需要这三个字符集都一致才能正确导入。4.1 查询 oracle server 端的字符集 有很多种方法
5、可以查出 oracle server 端的字符集,比较直观的查询方法是以下这种:SQL select userenv(language) from dual;USERENV(LANGUAGE)-SIMPLIFIED CHINESE_CHINA.ZHS16GBKSQLselect userenv(language) from dual; AMERICAN _ AMERICA. ZHS16GBK 4.2 如何查询 dmp 文件的字符集 用 oracle 的 exp 工具导出的 dmp 文件也包含了字符集信息,dmp 文件的第 2 和第 3 个字节记录了 dmp 文件的字符集。如果 dmp 文件不大
6、,比如只有几 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 也可以得到它对应的字
7、符集。4.3 查询 oracle client 端的字符集 在 windows 平台下,就是注册表里面相应 OracleHome 的NLS_LANG。还可以在 dos 窗口里面自己设置,比如: set nls_lang=AMERICAN_AMERICA.ZHS16GBK 这样就只影响这个窗口里面的环境变量。 在 unix 平台下,就是环境变量 NLS_LANG。 $echo $NLS_LANG AMERICAN_AMERICA.ZHS16GBK 如果检查的结果发现 server 端与 client 端字符集不一致,请统一修改为同 server 端相同的字符集。补充:(1).数据库服务器字符集s
8、elect * from nls_database_parameters来源于 props$,是表示数据库的字符集。(2).客户端字符集环境select * from nls_instance_parameters其来源于 v$parameter,表示客户端的字符集的设置,可能是参数文件,环境变量或者是注册表(3).会话字符集环境select * from nls_session_parameters来源于 v$nls_parameters,表示会话自己的设置,可能是会话的环境变量或者是 alter session 完成,如果会话没有特殊的设置,将与 nls_instance_paramete
9、rs 一致。(4).客户端的字符集要求与服务器一致,才能正确显示数据库的非Ascii 字符。如果多个设置存在的时候,NLS 作用优先级别:Sql function alter session 环境变量或注册表 参数文件 数据库默认参数字符集要求一致,但是语言设置却可以不同,语言设置建议用英文。如字符集是 zhs16gbk,则 nls_lang 可以是American_America.zhs16gbk。五 修改 oracle 的字符集 按照上文所说,数据库字符集在创建后原则上不能更改。因此,在设计和安装之初考虑使用哪一种字符集十分重要。对数据库 server而言,错误的修改字符集将会导致很多不可
10、测的后果,可能会严重影响数据库的正常运行,所以在修改之前一定要确认两种字符集是否存在子集和超集的关系。一般来说,除非万不得已,我们不建议修改 oracle 数据库 server 端的字符集。特别说明,我们最常用的两种字符集 ZHS16GBK 和 ZHS16CGB231280 之间不存在子集和超集关系,因此理论上讲这两种字符集之间的相互转换不受支持。 不过修改字符集有 2 种方法可行。1. 通常需要导出数据库数据,重建数据库,再导入数据库数据的方式来转换。2. 通过 ALTER DATABASE CHARACTER SET 语句修改字符集,但创建数据库后修改字符集是有限制的,只有新的字符集是当前
11、字符集的超集时才能修改数据库字符集,例如 UTF8 是 US7ASCII 的超集,修改数据库字符集可使用 ALTER DATABASE CHARACTER SET UTF8。 5.1 修改 server 端字符集(不建议使用) 1. 关闭数据库SQLSHUTDOWN IMMEDIATE2. 启动到 MountSQLSTARTUP MOUNT; SQLALTER SYSTEM ENABLE RESTRICTED SESSION; SQLALTER SYSTEM SET JOB_QUEUE_PROCESSES=0; SQLALTER SYSTEM SET AQ_TM_PROCESSES=0; SQ
12、LALTER DATABASE OPEN; -这里可以从父集到子集SQLALTER DATABASE CHARACTER SET ZHS16GBK; SQLALTER DATABASE NATIONAL CHARACTER SET ZHS16GBK; -如果是从子集到父集,需要使用 INTERNAL_USE 参数,跳过超子集检测SQLALTER DATABASE CHARACTER SET INTERNAL_USE AL32UTF8; SQLALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE AL32UTF8;SQLSHUTDOWN IMMED
13、IATE; SQLSTARTUP注意:如果没有大对象,在使用过程中进行语言转换没有什么影响,(切记设定的字符集必须是 ORACLE 支持,不然不能 start) 按上面的做法就可以。若出现ORA-12717: Cannot ALTER DATABASE NATIONAL CHARACTER SET when NCLOB data exists 这样的提示信息,要解决这个问题有两种方法1. 利用 INTERNAL_USE 关键字修改区域设置,2. 利用 re-create,但是 re-create 有点复杂,所以请用internal_useSQLSHUTDOWN IMMEDIATE;SQLSTA
14、RTUP MOUNT EXCLUSIVE;SQLALTER SYSTEM ENABLE RESTRICTED SESSION;SQLALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;SQLALTER SYSTEM SET AQ_TM_PROCESSES=0;SQLALTER DATABASE OPEN;SQLALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE UTF8;SQLSHUTDOWN immediate;SQLstartup;如果按上面的做法做,National charset 的区域设置就没有问题5.2 修
15、改 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 无法打开,就需要用程序的方法了。5.3 客户端字符集设置方法1)UNIX 环境$NLS_LANG=“simplified chinese”_china.zhs16gbk$export NLS_LANG编辑 oracle 用户的 profile 文件2)Windows 环境编辑注册表R