首页 » ORACLE » US7ASCII DMP 导入 ZHS16GBK DB 一方案

US7ASCII DMP 导入 ZHS16GBK DB 一方案

朋友有个EXP 导出的文件,因为源端导出是US7ASCII,导入ZHS16GBK总是乱码。

Oracle的字符集命名遵循以下命名规则:
<Language><bit size><encoding>
即: <语言><比特位数><编码>

可以查询以下数据字典或视图查看字符集设置情况
nls_database_parameters、props$、v$nls_parameters

imp导入时验证三方的字符集,

1. oracel server端的字符集(TARGET DB); 2. oracle client端的字符集(OS  ENV); 3. dmp文件的字符集。

下面是我的方法。9I导出的DMP 文件。导入我用的是10205 的客户端导入10205的DB.

1、导出
export NLS_LANG=AMERICAN_AMERICA.US7ASCII

2,尝试导入失败

[oracle@oem ~]$ env |grep LANG
NLS_LANG=american_america.US7ASCII
LANG=SIMPLIFIED CHINESE.ZHS16GBK
[oracle@oem ~]$ imp system/oracle fromuser=dagluser touser=test tables=NZ_DJB file=haidianbiaoqian.dmp 

import done in US7ASCII character set and AL16UTF16 NCHAR character set
import server uses ZHS16GBK character set (possible charset conversion)
. importing DAGLUSER's objects into TEST
. . importing table                       "NZ_DJB"     303243 rows imported
Import terminated successfully without warnings.

SQL> select * from NLS_database_PARAMETERS;

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE                   AMERICAN
NLS_TERRITORY                  AMERICA
NLS_CURRENCY                   $
NLS_ISO_CURRENCY               AMERICA
NLS_NUMERIC_CHARACTERS         .,
NLS_CHARACTERSET               ZHS16GBK
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD-MON-RR
NLS_DATE_LANGUAGE              AMERICAN
NLS_SORT                       BINARY
NLS_TIME_FORMAT                HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT           DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT             HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT        DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY              $
NLS_COMP                       BINARY
NLS_LENGTH_SEMANTICS           BYTE
NLS_NCHAR_CONV_EXCP            FALSE
NLS_NCHAR_CHARACTERSET         AL16UTF16
NLS_RDBMS_VERSION              10.2.0.5.0

SQL> select NZ_DJB.QYMC from test.nz_djb where rownum<10;

QYMC
--------------------------------------------------------------------------------
????????????????????????????
????????????????????????????????????????
??????????????????????????????????????
????????????????????????
??????????????????????????
????????????????????????????
????????????????????????????????
????????????????????????????????
??????????????????????????????????????????

[oracle@oem ~]$ env |grep LANG                       
NLS_LANG=american_america.US7ASCII
LANG=american_america.US7ASCII

--导入同样乱码, 删除表,再接着下面的修改。

下面是用UltraEdit(专业文本/十六进制编辑器版本 17.30.0.1011)打下dmp 文件的16进制显示部分样式已截取
03 00 01 45 58 50 4F 52 54 ...
2E 30 31 0A 44 47 4C 55 53 ...
53 45 52 53 0A 32 30 34 38 ...
0A 00 01 00 01 07 D0 00 01 ...

注意第2,3 byte内容,为00 01 转换为10进制 1,也就是这个dmp文件的字符集编号为1,下面使用NLS_CHARSET_NAME function转换一下字符集的名称
sys@ANBOB>select nls_charset_name(to_number('0001','xxxx')) from dual;
NLS_CHARSET_NAME(TO_NUMBER('0001','XXXX'
----------------------------------------
US7ASCII

可以看到那个dmp文件的字符集是US7ASCII,如果要替换为ZHS16GBK,我们需要转换一对应的编号,使用NLS_CHARSET_ID function
sys@ANBOB>select to_char(nls_charset_id('ZHS16GBK'),'xxxxxxxxxx') from dual;
TO_CHAR(NLS
-----------
        354
另外注意经过测试只修改第2、3 BYTE导入依旧乱码,还要修改第二处,位置我发现不固定,我暂时没有找到dmp file header结构,
目前发现是在UE 16进制显示的第4行如上面UE的红色字体,处于07 D0 00前面的两个字节,有时是第3、4,本例打开是第4、5,也是US7ASCII,同样需要修改为ZHS16GBK对应的0354.

修改后
03 03 54 45 58 50 4F 52 54 ...
2E 30 31 0A 44 47 4C 55 53 ...
53 45 52 53 0A 32 30 34 38 ...
0A 00 01 03 54 07 D0 00 01 ...

2、编辑DMP文件(ultraedit) 修改第一行:2,3字节(0001)为0354 如果DMP 文件过大可使用linux工具截取转换
cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6

注意在linux下显示高低位置颠倒,上面的dmp ,修改后od时显示如下

[oracle@db231 ~]$ cat haidianbiaoqian.dmp|od -x|head -4
0000000 0303 4554 5058 524f 3a54 3056 2e39 3030
0000020 302e 0a31 4444 4741 554c 4553 0a52 5552
0000040 4553 5352 320a 3430 0a38 0a30 3032 300a
0000060 000a 0301 0754 00d0 0001 0000 0000 0000

 

3、再次导入

[oracle@oem ~]$ export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

[oracle@oem ~]$ export LANG=AMERICAN_AMERICA.ZHS16GBK

[oracle@oem ~]$ env |grep LANG

NLS_LANG=AMERICAN_AMERICA.ZHS16GBK

LANG=AMERICAN_AMERICA.ZHS16GBK

[oracle@db231 ~]$ imp system/oracle file=haidianbiaoqian.dmp touser=weejar  fromuser=DAGLUSER  tables=NZ_DJB
Import: Release 11.2.0.3.0 – Production on Fri Jun 13 13:24:10 2014
Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.
Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 – 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Export file created by EXPORT:V09.00.01 via conventional path
Warning: the objects were exported by DAGLUSER, not by you

import done in ZHS16GBK character set and AL16UTF16 NCHAR character set
. importing DAGLUSER’s objects into WEEJAR
. . importing table                       “NZ_DJB”     303243 rows imported
Import terminated successfully without warnings.

 

4,在另一客户端WINDOWS查询

C:\>set NLS_LANG=american_america.zhs16gbk

C:\>sqlplus weejar/weejar@192.168.168.231:1521/anbob.com

SQL*Plus: Release 10.2.0.1.0 – Production on Mon Jan 28 14:31:26 2013

Copyright (c) 1982, 2005, Oracle. All rights reserved.

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 – 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select NZ_DJB.QYMC from nz_djb where rownum<10;

QYMC
——————————————————————————–
北京XXX房地产开发有限公司
北京XXX贸有限公司物业管理分公司
北京XX讯器材有限公司北太平庄分公司
北京XX业科技有限公司
北京XX电子技术有限公司
北京XX视业文化传播有限公司
北京XXXXX生物技术有限责任公司
北京羽XXXX美发中心学院路咨询部
北京市声XXX有限公司第一销售分公司

9 rows selected.

–DONE.

SUMMARY:

exp 时注意保证三处的字符集一致,对于本例的US7ASCII(10g)   DMP 导入 ZHS16GBK DB (11g), 采用了修改dmp文件中的两处字符集编号,最终解决了字符集乱码问题。

 

打赏

,

对不起,这篇文章暂时关闭评论。