1. 字符集的一些概念:
与ORACLE数据库相连时,有一个很重要的环境变量需要设定:NLS_LANG,其格式为:
NLS_LANG = <Language>_<Territory>.<Clients Charactset>
<Language> 指定Oracle 消息的语言,如:AMERICAN
<Territory> 指地区,如:AMERICA
<Clients Charactset> 指控制客户端的应用程序的字符集,如:WE8ISO8859P1
如果<Clients Charactset>设置不好,数据库中的字符可能显示成乱码或?,特别是在使用UNICODE编码之后。
在建库时,一旦选定字符集,则数据库中字符的存储就受到相应的限制,选择最合适的字符集时需要慎重考虑。字符集的命名基本采用以下规则(Oracle8中的UTF8就不用此规则):
<语言><比特位><编码>,如 <ZHS><16><GBK>
数据库所使用的字符集可以通过如下方式来获得:
SELECT Value FROM V$NLS_PARAMETERS
WHERE PARAMETER='NLS_CHARACTERSET';
2. 导出/导入转换时字符集的问题:
在建立数据库之后,对字符集的修改虽然有 alter database character set '字符集名称' 方式,但一般不提倡这样修改数据库的字符集。
导出/导入通常作为数据库升级的一种手段。一般不提倡直接修改数据库字符集,所以导出/导入可以作为修改数据库字符集的一种方法。
假如A库为原库(导出库), B库为目标库(导入库),在导出、导入时将出现很多种情况:
(1) 那么当A库字符集与B库字符集一样,此时客户端NLS_LANG设置为A,B库的字符集做导出/导入即可;
(2) A库字符集是B库字符集的子集(A库中的所有字符都可以在B库中以相同代码标识)时,客户端NLS_LANG设置为A库的字符集做导出后,可以直接导入到B库,转换只发生在B库服务器端;
(3) 当A库字符集与B库字符集不同,且不是B库字符集的子集时,导入到B库的部分字符就会出现乱码。但是,有一部分字符集之间的转换可以通过修改库导出文件中的相关字符集信息部分来实现(大家在做实际转换前可以先多做测试,以确保导入后不出现字符集问题)。
下面我们来看一下库导出文件的一些信息:
EXP导出库的文件中包含库字符集信息,为第二、三字节内容,如A库的字符集为:WE8ISO8859P1,则第二、三字节的内容为: 00 1F (31),而ZHS16GBK则为 03 54(852)
字符集所对应的ID可通过系统函数NLS_CHARSET_ID来获得:
SELECT NLS_CHARSET_ID(Value) Nls_Charset_ID, Value,
TO_CHAR(Nls_Charset_ID(Value),'xxxx') Hex_ID FROM V$NLS_VALID_VALUES
WHERE Parameter='CHARACTERSET';
经测试发现:将图中ABC三处的00 1F改为 03 54并保存,再导入到字符字符集为ZHS16GBK的库时,原来的中文可以正常显示。
A. 客户端的字符集改为导出数据库的字符集, 然后导出(如A库为 UTF8, 则客户端字符集可设定为 AMERICAN_AMERICA.UTF8);
D:\>exp userid=jason/oracle file=utf8.dmp tables=test
Export: Release 9.2.0.8.0 - Production on Tue Apr 29 11:24:03 2008
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to: Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
Export done in UTF8 character set and AL16UTF16 NCHAR character set
About to export specified tables via Conventional Path ...
. . exporting table TEST 2 rows exported
Export terminated successfully without warnings.
修改前
修改后
C. 然后将客户端字符集改为导入数据库的字符集,然后导入(如B库为ZHS16GBK,则客户端字符可设定为AMERICAN_AMERICA.ZHS16GBK)
D:\>imp userid=jason/oracle file=bb.dmp full=y ignore=y
Import: Release 9.2.0.8.0 - Production on Tue Apr 29 14:18:15 2008
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to: Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
Export file created by EXPORT:V09.02.00 via conventional path
import done in ZHS16GBK character set and AL16UTF16 NCHAR character set
. importing JASON's objects into JASON
. . importing table "TEST" 2 rows imported
Import terminated successfully without warnings.
D:\>sqlplus /nolog
SQL*Plus: Release 9.2.0.8.0 - Production on Tue Apr 29 14:18:17 2008
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
SQL> connect jason/oracle
Connected.
SQL> select * from test;
A1
----------
一二
三四
SQL>