3.4 NLS_LANG 的设置与影响
导入导出(IMP/EXP)是一个常用的数据迁移及转化工具,因其导出文件具有平台无关性,所以在跨平台迁移中,最为常用;进一步的,从 Oracle10g 开始,数据泵(IMPDP/EXPDP)作为新一代高效数据导入导出工具被引入进来。
在使用 EXP 工具进行导出操作时,非常重要的是客户端的字符集设置,也就是客户端的NLS_LANG设置。
NLS_LANG参数由以下部分组成:
NLS_LANG=<Language>_<Territory>.<ClientsCharacterset>
其中LANGUAGE参数指定Oracle消息使用的语言,日期中月份和日的显示;TERRITORY参数指定货币和数字格式,地区和计算星期及日期的习惯;CHARACTERSET控制客户端应用程序使用的字符集,这个字符集用于对数据库传输过来的数据进行解码。
来看一个简单的测试,来了解一下这几个参数的作用及其对于数据显示的影响,在LANGUAGE设置为简体中文时,提示是中文输出:
E:\>set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
E:\>sqlplus "/ as sysdba"
连接到:Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
SQL> select sysdate from dual;
SYSDATE
----------
01-11月-03
已选择 1 行。
当LANGUAGE设置为American时,提示信息等是英文输出:
E:\>set NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
E:\>sqlplus "/ as sysdba"
Connected to:Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
SQL> select sysdate from dual;
SYSDATE
---------
01-NOV-03
1 row selected.
客户端的NLS_LANG设置不仅影响数据转储,还会影响到查询显示,是极其重要的参数。查看客户端NLS_LANG设置可以使用以下方法。
Windows客户端的NLS_LANG设置受注册表参数影响,所以可从注册表中找到当前的参数设置,具体键值位于HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\下。
对于不同的版本,其具体键值可能不同,如Oracle 10g的键值可能为KEY_OraDb10g,Oracle 11g的键值可能为KEY_OraDb11g_home1,其他客户端安装可能使用键值HOMExx\(xx指存在多个ORACLE_HOME时系统编号)。
通常需要设置这相应键值下的NLS_LANG和数据库字符集相同,以避免查询乱码等麻烦。
在UNIX环境下可以使用从环境变量中取得当前的NLS_LANG设置,例如:
[oracle@wapdb ~]$ env|grep NLS
NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
传统的导入和导出工具(IMP/EXP)是客户端软件,同 SQL*PLUS 和 Oracle Forms 一样,因此,使用EXP/IMP工具将同样按照NLS_LANG定义的方式调用字符集文件,并且在服务器和客户端之间根据设置进行字符集转换:
[oracle@wapdb ~]$ export NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
[oracle@wapdb ~]$ strace -o exp.log exp
Export: Release 11.1.0.6.0 - Production on星期一 9月 27 10:39:05 2010
Copyright (c) 1982, 2007, Oracle. All rights reserved.
Username:
Password:
[oracle@wapdb ~]$ grep nls exp.log
open("/opt/oracle/product/11.1.0/nls/data/lx1boot.nlb", O_RDONLY) = 3
open("/opt/oracle/product/11.1.0/nls/data/lx00023.nlb", O_RDONLY) = 3
open("/opt/oracle/product/11.1.0/nls/data/lx20354.nlb", O_RDONLY) = 3
open("/opt/oracle/product/11.1.0/nls/data/lx10035.nlb", O_RDONLY) = 3
open("/opt/oracle/product/11.1.0/nls/data/lx20001.nlb", O_RDONLY) = 3
open("/opt/oracle/product/11.1.0/nls/data/lx00001.nlb", O_RDONLY) = 3
open("/opt/oracle/product/11.1.0/nls/data/lx10001.nlb", O_RDONLY) = 3
open("/opt/oracle/product/11.1.0/nls/data/lx207d0.nlb", O_RDONLY) = 9
在执行导出数据操作时,导出使用的字符集将会记录在导出的DMP文件中,当文件导入时,将会检查导出时使用的字符集设置,如果这个字符集不同于导入客户端的NLS_LANG设置,字符集将根据导入客户端NLS_LANG设置进行转换,如果必要,在数据插入数据库之前还会进行进一步转换。
所以通常在执行导出操作时,最好把客户端字符集设置得和数据库相同,这样可以避免在导出时发生不必要的数据转换,导出文件将和数据库具有相同的字符集,数据得以完好备份。即使将来会把导出文件导入到不同字符集的数据库中,这样做也可以把转换延缓至导入时刻。