字符集问题的初步探讨(三)

 4. 导入导出及转换

 

导入导出是我们常用的一个数据迁移及转化工具,因其导出文件具有平台无关性,所以在跨平台迁移中,最为常用。
在导出操作时,非常重要的是客户端的字符集设置,也就是客户端的NLS_LANG设置。
NLS_LANG参数由以下部分组成:

NLS_LANG =< Language > _ < Territory > . < Clients Characterset >

 

NLS_LANG各部分含义如下:
LANGUAGE指定:
-Oracle消息使用的语言
-日期中月份和日显示
TERRITORY指定
-货币和数字格式
-地区和计算星期及日期的习惯
CHARACTERSET:
-控制客户端应用程序使用的字符集
通常设置或者等于客户端(如Windows)代码页
或者对于unicode应用设置为UTF8
在Windows上查看当前系统的代码页可以使用chcp命令:

 

E: > chcp
 活动的代码页: 
936

代码页936也就是中文字符集 GBK,在Microsoft的官方站点上,我们可以遭到关于936代码页的具体编码规则,请参考以下链接:


http://www.microsoft.com/globaldev/reference/dbcs/936.htm

我们看一个简单的测试,来了解一下这几个参数的作用:

 

E: > set  NLS_LANG = SIMPLIFIED CHINESE_CHINA.ZHS16GBK

E:
> sqlplus " /   as  sysdba"

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  星期六 11月  1   22 : 51 : 59   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


连接到:
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  行。

SQL
>   exit
从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中断开

E:
> set  NLS_LANG = AMERICAN_AMERICA.ZHS16GBK

E:
> sqlplus " /   as  sysdba"

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  Sat Nov  1   22 : 52 : 24   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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.

SQL
>

 

查看客户端NLS_LANG设置可以使用以下方法:

 

Windows使用:


echo 
% NLS_LANG %
如:
E:
> echo  % NLS_LANG %
AMERICAN_AMERICA.ZHS16GBK




Unix使用:

env
| grep NLS_LANG
如:
/ opt / oracle > env | grep NLS_LANG
NLS_LANG
= AMERICAN_CHINA.ZHS16GBK

Windows客户端设置,可以在注册表中更改NLS_LANG,具体键值位于:
HKEY_LOCAL_MACHINESOFTWAREORACLEHOMExx
xx指存在多个ORACLE_HOME时系统编号。

 

导入和导出是客户端产品,同SQL*PLUS和Oralce Forms一样,因此,使用EXP/IMP工具将按照NLS_LANG定义的方式转换字符集。

导出使用的字符集将会记录在导出文件中,当文件导入时,将会检查导出时使用的字符集设置,如果这个字符集不同于导入客户端的NLS_LANG
设置,字符集将根据导入客户端NLS_LANG设置进行转换,如果必要,在数据插入数据库之前会进行进一步转换。

通常在导出时最好把客户端字符集设置得和数据库端相同,这样可以避免在导出时发生不必要的数据转换,导出文件将和数据库具有相同的字符集。
即使将来会把导出文件导入到不同字符集的数据库中,这样做也可以把转换延缓至导入时刻。

当进行数据导入时,主要存在以下两种情况:
1.源数据库和目标数据库具有相同字符集设置
这时,只需要设置NLS_LANG等于数据库字符集即可导入(前提是,导出使用的是和源数据库相同字符集,即三者相同)

2.源数据库和目标数据库字符集不同
如果我们导出时候使用的NLS_LANG是和源数据库相同的字符集,那么导入时就可以设置客户端NLS_LANG等于导出时使用的字符集,这
样转换只发生在数据库端,而且只发生一次。

例如:
如果进行从WE8MSWIN1252到UTF8的转换
1)使用NLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252导出数据库。
这时创建的导出文件包含WE8MSWIN1252的数据
2)导入时使用NLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252
这时转换仅发生在insert数据到UTF8的数据库中。

以上假设的转换只在目标数据库字符集是源数据库字符集的超集时才能转换。如果不同,一般就需要进行一些特殊的处理。

我们简单看一下导入的转换过程(以Oracle8i为例):

1.确定导出数据库字符集环境
通过读取导出文件头,可以获得导出文件的字符集设置
2.确定导入session的字符集,即导入Session使用的NLS_LANG环境变量
3.IMP读取导出文件
读取导出文件字符集ID,和导入进程的NLS_LANG进行比较
4.如果导出文件字符集和导入Session字符集相同,那么在这一步骤内就不需要转换
如果不同,就需要把数据转换为导入Session使用的字符集。
然而这种转换只能在单byte字符集之间进行。
我们看一个测试:

E: ls2 > set  NLS_LANG = AMERICAN_AMERICA.US7ASCII

设置导入session NLS_LANG为US7ASCII

E: ls2
> e:oracleora8iinimp eygle / eygle  file = Sus7ascii - Cus7ascii - exp817.dmp fromuser = eygle touser = eygle tables = test

这个导出文件是从US7ASCII数据库导出,导出客户端NLS_LANG也是US7ASCII

Import: Release 
8.1 . 7.1 . 1   -  Production  on  Fri Nov  7   00 : 59 : 22   2003

(c) Copyright 
2000  Oracle Corporation.   All  rights reserved.

Connected 
to : Oracle8i Enterprise Edition Release  8.1 . 7.1 . 1   -  Production
With  the Partitioning  option
JServer Release 
8.1 . 7.1 . 1   -  Production

这时导入,在DMP文件和NLS_LANG之间不需要进行字符集转换。

Export 
file  created  by  EXPORT:V08. 01.07  via conventional path
import done 
in  US7ASCII  character   set   and  ZHS16GBK  NCHAR   character   set
import server uses ZHS16GBK 
character   set  (possible charset conversion)
export server uses UTF8 
NCHAR   character   set  (possible ncharset conversion)
. . importing 
table                          "TEST"           2  rows imported
Import terminated successfully without warnings.

 

5.对于多Byte字符集的导入(如:UTF8)
需要设置导入Session字符集和导出字符集相同
否则就会遇到:IMP-16 "Required character set conversion (type %lu to %lu) not supported" 错误。

 

E: ls2 > set  NLS_LANG = AMERICAN_AMERICA.ZHS16GBK

导入Session字符集设置为ZHS16GBK
导入US7ASCII的导出文件

E: ls2
> e:oracleora8iinimp eygle / eygle  file = Sus7ascii - Cus7ascii - exp817.dmp fromuser = eygle touser = eygle

Import: Release 
8.1 . 7.1 . 1   -  Production  on  Fri Nov  7   00 : 38 : 55   2003

(c) Copyright 
2000  Oracle Corporation.   All  rights reserved.


Connected 
to : Oracle8i Enterprise Edition Release  8.1 . 7.1 . 1   -  Production
With  the Partitioning  option
JServer Release 
8.1 . 7.1 . 1   -  Production

IMP
- 00016 : required  character   set  conversion (type  1   to   852 not  supported
IMP
- 00000 : Import terminated unsuccessfully

在从导出文件US7ASCII到导入 NLS_LANG设置为ZHS16GBK的过程中,不支持单Byte字符集向多Byte转换,报出以上错误。

 

6.导入Session字符集应该是导出字符集的超级,否则,专有的字符将难以正确转换。
7.当数据转换为导入Session字符集设置以后,如果导入Session字符集不同于导入数据库字符集,这时还需要最后一步转换,这要求导入数据库字符
集是导入session字符集的超级,否则某些专有字符将不能正常转换。
我们继续看上面的两个过程,这里有这样两个原则:
1.如果NLS_LANG的设置和数据库相同,那么数据(在传输过程中当然是2进制码)不经过转换就直接插入数据库中。
2.如果NLS_LANG的设置和数据库不同,那么数据需要转换后才能插入数据库中。
我们再回头来看上面的第一个例子:

 

Export  file  created  by  EXPORT:V08. 01.07  via conventional path
import done 
in  US7ASCII  character   set   and  ZHS16GBK  NCHAR   character   set
import server uses ZHS16GBK 
character   set  (possible charset conversion)
export server uses UTF8 
NCHAR   character   set  (possible ncharset conversion)
. . importing 
table                          "TEST"           2  rows imported
Import terminated successfully without warnings.

这时候经过第一步转换后的数据,US7ASCII到ZHS16GBK丢失首位,原样插入数据库,我们看到这时数据库中存放的就是错误的字符(在后面部分我们做了详细的转换):

E: ls2
> sqlplus eygle / eygle

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  Fri Nov  7   00 : 35 : 39   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


Connected 
to :
Oracle8i Enterprise Edition Release 
8.1 . 7.1 . 1   -  Production
With  the Partitioning  option
JServer Release 
8.1 . 7.1 . 1   -  Production

SQL
>   select   *   from  test;

NAME
-- ------------------
2bJT
test

 

在Oracle9i中,以上情况略有不同。

5. 如何识别导出文件的字符集

我们知道在导出文件中,记录着导出使用的字符集id,通过查看导出文件头的第2、3个字节,我们可以找到16进制表示的字符集ID,在Windows上,
我们可以使用UltraEdit等工具打开dmp文件,查看其导出字符集::

在Unix上我们可以通过以下命令来查看:

 

cat expdat.dmp  |  od  - |  head

 

Oracle提供标准函数,对字符集名称及ID进行转换:

 

SQL >   select  nls_charset_id( ' ZHS16GBK ' from  dual;

NLS_CHARSET_ID(
' ZHS16GBK ' )
-- ------------------------
                        852

1  row selected.

SQL
>   select  nls_charset_name( 852 from  dual;

NLS_CHAR
-- ------
ZHS16GBK

1  row selected.

十进制转换十六进制:

SQL
>   select  to_char( ' 852 ' , ' xxxx ' from  dual;

TO_CH
-- ---
   354

1  row selected.

 

对应上面的图中第2、3字节,我们知道该导出文件字符集为ZHS16GBk.

查询数据库中有效的字符集可以使用以下脚本:

 

col nls_charset_id  for   9999
col nls_charset_name 
for  a30
col hex_id 
for  a20
select  
nls_charset_id(value) nls_charset_id,  
value nls_charset_name,
to_char(nls_charset_id(value),
' xxxx ' ) hex_id
from   v$nls_valid_values
where  parameter  =   ' CHARACTERSET '
order   by  nls_charset_id(value)
/

 

输出样例如下:

 

 
NLS_CHARSET_ID NLS_CHARSET_NAME               HEX_ID
-------------- ------------------------------ -------------
1 US7ASCII 1
2 WE8DEC 2
3 WE8HP 3
4 US8PC437 4
5 WE8EBCDIC37 5
6 WE8EBCDIC500 6
7 WE8EBCDIC1140 7
8 WE8EBCDIC285 8
...................
850 ZHS16CGB231280 352
851 ZHS16MACCGB231280 353
852 ZHS16GBK 354
853 ZHS16DBCS 355
860 ZHT32EUC 35c
861 ZHT32SOPS 35d
862 ZHT16DBT 35e
863 ZHT32TRIS 35f
864 ZHT16DBCS 360
865 ZHT16BIG5 361
866 ZHT16CCDC 362
867 ZHT16MSWIN950 363
868 ZHT16HKSCS 364
870 AL24UTFFSS 366
871 UTF8 367
872 UTFE 368

..................................





 

在很多时候,当我们进行导入操作的时候,已经离开了源数据库,这时如果目标数据库的字符集和导出文件不一致,很多时候就需要进行特殊处理,
以下介绍几种方法,主要以US7ASCII和ZHS16GBK为例

1. 源数据库字符集为US7ASCII,导出文件字符集为US7ASCII或ZHS16GBK,目标数据库字符集为ZHS16GBK
在Oracle92中,我们发现对于这种情况,不论怎样处理,这个导出文件都无法正确导入到Oracle9i数据库中,这可能是因为Oracle9i的编码方案发生了较大改变。

以下是我们所做的简单测试,其中导出文件命名规则为:


S-Server ,后跟Server字符集
C-client , 后跟导出操作时客户端字符集


导入时客户端字符集设置在命令行完成,限于篇幅,我们省略了部分测试过程。
对于Oracle9iR2,我们的测试结果是US7ASCII字符集,不管怎样转换,都无法正确导入ZHS16GBK字符集的数据库中。

在进行导入操作时,如果字符不能正常转换,Oracle数据库会自动用一个”?”代替,也就是编码63。

 

E: ls2 > set  NLS_LANG = AMERICAN_AMERICA.US7ASCII

E: ls2
> imp eygle / eygle  file = Sus7ascii - Cus7ascii.dmp fromuser = eygle touser = eygle tables = test

Import: Release 
9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 14 : 39   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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

Export 
file  created  by  EXPORT:V09. 02.00  via conventional path
import done 
in  US7ASCII  character   set   and  AL16UTF16  NCHAR   character   set
import server uses ZHS16GBK 
character   set  (possible charset conversion)
. . importing 
table                          "TEST"           2  rows imported
Import terminated successfully without warnings.

E: ls2
> sqlplus eygle / eygle

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 14 : 50   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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  name, dump (name)  from  test;

NAME    
DUMP (NAME)
-- ---------------------------
????    Typ = 1   Len = 4 63 , 63 , 63 , 63
test    Typ
= 1   Len = 4 116 , 101 , 115 , 116

2  rows selected.

SQL
>   exit
Disconnected 
from  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

E: ls2
> set  NLS_LANG = AMERICAN_AMERICA.ZHS16GBK

E: ls2
> imp eygle / eygle  file = Sus7ascii - Cus7ascii.dmp fromuser = eygle touser = eygle tables = test ignore = y

Import: Release 
9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 15 : 28   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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

Export 
file  created  by  EXPORT:V09. 02.00  via conventional path
import done 
in  ZHS16GBK  character   set   and  AL16UTF16  NCHAR   character   set
export client uses US7ASCII 
character   set  (possible charset conversion)
. . importing 
table                          "TEST"           2  rows imported
Import terminated successfully without warnings.

E: ls2
> sqlplus eygle / eygle

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 15 : 34   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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  name, dump (name)  from  test;

NAME        
DUMP (NAME)
-- ------------------------------------------------------------------------------
????        Typ = 1   Len = 4 63 , 63 , 63 , 63
test        Typ
= 1   Len = 4 116 , 101 , 115 , 116
????        Typ
= 1   Len = 4 63 , 63 , 63 , 63
test        Typ
= 1   Len = 4 116 , 101 , 115 , 116


4  rows selected.

SQL
>   drop   table  test;

Table  dropped.

SQL
>   exit
Disconnected 
from  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

E: ls2
> set  NLS_LANG = AMERICAN_AMERICA.ZHS16GBK

E: ls2
> imp eygle / eygle  file = Sus7ascii - Czhs16gbk.dmp fromuser = eygle touser = eygle tables = test ignore = y

Import: Release 
9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 17 : 21   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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

Export 
file  created  by  EXPORT:V09. 02.00  via conventional path
import done 
in  ZHS16GBK  character   set   and  AL16UTF16  NCHAR   character   set
. . importing 
table                          "TEST"           2  rows imported
Import terminated successfully without warnings.

E: ls2
> sqlplus eygle / eygle

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 17 : 30   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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  name, dump (name)  from  test;

NAME    
DUMP (NAME)
-- --------------------------------------------
????    Typ = 1   Len = 4 63 , 63 , 63 , 63
test    Typ
= 1   Len = 4 116 , 101 , 115 , 116

2  rows selected.

SQL
>   exit
Disconnected 
from  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

E: ls2
> set  NLS_LANG = AMERICAN_AMERICA.US7ASCII

E: ls2
> imp eygle / eygle  file = Sus7ascii - Czhs16gbk.dmp fromuser = eygle touser = eygle tables = test ignore = y

Import: Release 
9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 18 : 00   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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

Export 
file  created  by  EXPORT:V09. 02.00  via conventional path
import done 
in  US7ASCII  character   set   and  AL16UTF16  NCHAR   character   set
import server uses ZHS16GBK 
character   set  (possible charset conversion)
export client uses ZHS16GBK 
character   set  (possible charset conversion)
. . importing 
table                          "TEST"           2  rows imported
Import terminated successfully without warnings.

E: ls2
> sqlplus eygle / eygle

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 18 : 08   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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  name, dump (name)  from  test;

NAME    
DUMP (NAME)
-- --------------------------------------
????    Typ = 1   Len = 4 63 , 63 , 63 , 63
test    Typ
= 1   Len = 4 116 , 101 , 115 , 116
????    Typ
= 1   Len = 4 63 , 63 , 63 , 63
test    Typ
= 1   Len = 4 116 , 101 , 115 , 116

4  rows selected.

SQL
>

 

对于这种情况,我们可以通过使用Oracle8i的导出工具,设置导出字符集为US7ASCII,导出后修改第二、三字符,修改 0001 为
0354,这样就可以将US7ASCII字符集的数据正确导入到ZHS16GBK的数据库中。

修改导出文件:

导入修改后的导出文件:

 

E: ls2 > set  NLS_LANG = AMERICAN_AMERICA.ZHS16GBK

E: ls2
> imp eygle / eygle  file = Sus7ascii - Cus7ascii - exp817.dmp fromuser = eygle touser = eygle tables = test

Import: Release 
9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 37 : 17   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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

Export 
file  created  by  EXPORT:V08. 01.07  via conventional path
import done 
in  ZHS16GBK  character   set   and  AL16UTF16  NCHAR   character   set
export server uses UTF8 
NCHAR   character   set  (possible ncharset conversion)
. . importing 
table                          "TEST"           2  rows imported
Import terminated successfully without warnings.

E: ls2
> sqlplus eygle / eygle

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  Mon Nov  3   17 : 37 : 23   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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  name, dump (name)  from  test;

NAME     
DUMP (NAME)
-- ------------------------------------------------------------------------------
测试       Typ = 1   Len = 4 178 , 226 , 202 , 212
Test        Typ
= 1   Len = 4 116 , 101 , 115 , 116

2  rows selected.

SQL
>

 

2. 使用create database的方法
如果导出文件使用的字符集是US7ASCII,目标数据库的字符集是ZHS16GBK,我们可以使用create database的方法来修改,具体如下:

SQL >  col parameter  for  a30
SQL
>  col value  for  a30
SQL
>   select   *   from  v$nls_parameters;

PARAMETER                      VALUE
-- ---------------------------- ------------------------------
NLS_LANGUAGE                   AMERICAN
NLS_TERRITORY                  AMERICA
NLS_CURRENCY                   $
NLS_ISO_CURRENCY               AMERICA
NLS_NUMERIC_CHARACTERS         .,
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD
- MON - RR
NLS_DATE_LANGUAGE              AMERICAN
NLS_CHARACTERSET               ZHS16GBK
NLS_SORT                       
BINARY
……………….

19  rows selected.

SQL
>   create   database   character   set  us7ascii;
create   database   character   set  us7ascii
*
ERROR at line 
1 :
ORA
- 01031 : insufficient  privileges


SQL
>   select   *   from  v$nls_parameters;

PARAMETER                      VALUE
-- ---------------------------- ------------------------------
NLS_LANGUAGE                   AMERICAN
NLS_TERRITORY                  AMERICA
NLS_CURRENCY                   $
NLS_ISO_CURRENCY               AMERICA
NLS_NUMERIC_CHARACTERS         .,
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD
- MON - RR
NLS_DATE_LANGUAGE              AMERICAN
NLS_CHARACTERSET               US7ASCII
NLS_SORT                       
BINARY
…………..

19  rows selected.

SQL
>   exit
Disconnected 
from  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

E: ls2
> set  nls_lang = AMERICAN_AMERICA.US7ASCII

E: ls2
> imp eygle / eygle  file = Sus7ascii - Cus7ascii.dmp fromuser = eygle touser = eygle

Import: Release 
9.2 . 0.4 . 0   -  Production  on  Sun Nov  2   14 : 53 : 26   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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

Export 
file  created  by  EXPORT:V09. 02.00  via conventional path
import done 
in  US7ASCII  character   set   and  AL16UTF16  NCHAR   character   set
import server uses ZHS16GBK 
character   set  (possible charset conversion)
. . importing 
table                          "TEST"           2  rows imported
Import terminated successfully without warnings.

E: ls2
> sqlplus eygle / eygle

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  Sun Nov  2   14 : 53 : 35   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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   *   from  test;

NAME
-- --------
测试
test

2  rows selected.

 

我们看到,当发出create database character set us7ascii命令时,数据库v$nls_parameters中的字符集设置随之更改,该参数影响导入进程,
更改后可以正确导入数据,重起数据库后,该设置恢复。

提示:v$nls_paraemters来源于x$nls_parameters,该动态性能视图影响导入操作;而nls_database_parameters来源于props$数据表,影响数据存储。

3. Oracle提供的字符扫描工具csscan

我们说以上的方法只是应该在不得已的情况下使用,其本质是欺骗数据库,强制导入数据,可能损失元数据。
如果要确保数据的完整性,应该使用csscan扫描数据库,找出所有不兼容的字符,然后通过编写相应的脚本及代码,在转换之后进行更新,确保数据的正确性。
我们简单看一下csscan的使用。

要使用csscan之前,需要以sys用户身份创建相应数据字典对象:

 

E: ls2 > sqlplus " /   as  sysdba"

SQL
* Plus: Release  9.2 . 0.4 . 0   -  Production  on  Sun Nov  2   19 : 42 : 07   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


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  instance_name  from  v$intance;
select  instance_name  from  v$intance
                          
*
ERROR at line 
1 :
ORA
- 00942 table   or   view  does  not  exist


SQL
>   select  instance_name  from  v$instance;

INSTANCE_NAME
-- --------------
penny

1  row selected.

SQL
>  @? / rdbms / admin / csminst.sql

User  created.


Grant  succeeded.

………..

 

这个脚本创建相应用户(csmig)及数据字典对象,扫描信息会记录在相应的数据字典表里。

我们可以在命令行调用这个工具对数据库进行扫描:

 

E: ls2 > csscan  FULL = Y FROMCHAR = ZHS16GBK TOCHAR = US7ASCII  LOG = US7check. log  CAPTURE = Y ARRAY = 1000000  PROCESS = 2


Character   Set  Scanner v1. 1  : Release  9.2 . 0.1 . 0   -  Production  on  Sun Nov  2   20 : 24 : 45   2003

Copyright (c) 
1982 2002 , Oracle Corporation.   All  rights reserved.


Username: eygle
/ eygle

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

Enumerating tables 
to  scan...

. process 
1  scanning SYS.SOURCE$ [ AAAABHAABAAAAIRAAA ]
. process 
2  scanning SYS.ATTRIBUTE$ [ AAAAEoAABAAAAhZAAA ]
. process 
2  scanning SYS.PARAMETER$ [ AAAAEoAABAAAAhZAAA ]
. process 
2  scanning SYS.METHOD$ [ AAAAEoAABAAAAhZAAA ]
……..
. process 
2  scanning SYSTEM.DEF$_AQERROR [ AAAA8fAABAAACWJAAA ]
. process 
1  scanning WMSYS.WM$ENV_VARS [ AAABeWAABAAAFMZAAA ]
………………….
. process 
2  scanning SYS.UGROUP$ [ AAAAA5AABAAAAGpAAA ]
. process 
2  scanning SYS.CON$ [ AAAAAcAABAAAACpAAA ]
. process 
1  scanning SYS. FILE $ [ AAAAARAABAAAABxAAA ]

Creating 
Database  Scan Summary Report...

Creating Individual Exception Report...

Scanner terminated successfully.

 

然后我们可以检查输出的日志来查看数据库扫描情况:

 

Database Scan Individual Exception Report


[Database Scan Parameters]

Parameter                                               Value                                          
------------------------------------------          ------------------------------------------------
Scan type                                                Full database                                  
Scan CHAR data?                                 YES                                            
Current database character set         ZHS16GBK                                       
New database character set              US7ASCII                                       
Scan NCHAR data?                              NO                                             
Array fetch buffer size                           1000000                                        
Number of processes                          2                                              
Capture convertible data?                   YES                                            
------------------------------------------          ------------------------------------------------

[Data Dictionary individual exceptions]


[Application data individual exceptions]

User  : EYGLE
Table : TEST
Column: NAME
Type  : VARCHAR2(10)
Number of Exceptions         : 1        
Max Post Conversion Data Size: 4        

ROWID                                  Exception Type         Size        Cell Data(first 30 bytes)    
--------------------------------     ------------------------     -------      ------------------------------
AAABpIAADAAAAAMAAA      lossy conversion                      测试                         
--------------------------------      -----------------------      -------      ------------------------------

 

不能转换的数据将会被记录下来,我们可以根据这些信息在转换之后,对数据进行相应的更新,确保转换无误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值