对于Oracle数据库之间的移植采用Oracle的导入导出工具(Import/Export)是一个比较好的策略。虽也可以利用第三方软件如Sybase 的Power designer中的Reverse Engineering 进行数据库结构重建,然后在进行较复杂的数据导入过程,但对于作业队列、快照等则不得不用手工来创建。而Export能将整个数据库、指定用户、指定表和相关的数据字典进行输出,Export输出的输出转存二进制文件包括了完全重建所有被选对象所需的命令。
本人在为某电厂MIS(Oracle数据库)数据采用Oracle的导入导出工具从Windows NT平台移植到Digital Unix平台时遇到的关于字符集的问题和总结出的经验与大家来分享。
1. 移植环境
原操作系统平台: Windows NT
数据库: Oracle 8.0.5 for Windows NT
服务器:HP NetServer LH3
目标操作系统平台:Digital Unix alpha V4.0
数据库:Oracle 8.0.4 for Digital Unix
服务器:ALPHASERVER ES40 小型机
2. 数据导出
在NT服务器上用Oracle导出工具进行数据导出,Oracle导出工具有命令行和图形界面两种方式。
本人直接用命令行方式进行数据导出:
c:> exp80 gxmisdba/manager file=c:expdat.dmp log=c:export.log
即将导出指定的用户...
. 正在导出用户GXMISDBA的外部函数程序库名称
. 正在导出用户GXMISDBA的对象类型定义
即将导出GXMISDBA的对象 ...
. 正在导出数据库链接
. 正在导出序号
. 正在导出群集定义
. 即将导出GXMISDBA的表通过常规路径 ...
. . 正在导出表 AAAAA 0 行被导出
. . 正在导出表 EVT_CARRIER_CONFIGURATION 0 行被导出
. . 正在导出表 TBL_AJ_AGKS 331 行被导出
.
.
.
. 正在导出同义词
. 正在导出视图
. 正在导出存储的过程
. 正在导出参考资料一致性约束条件
. 正在导出触发器
. 正在导出后期表活动
. 正在导出快照
. 正在导出快照日志
. 正在导出作业队列
. 正在导出刷新组和子组
在没有警告的情况下成功终止导出。
3.数据导入
在NT服务器上通过ftp命令将导出的输出转存二进制文件expdat.dmp(使用binary传输模式)传输至Digital Unix服务器上。
用Oracle for Digital Unix 数据导入工具命令行方式进行数据导入
$imp gxmisdba/manager file=/expdat.dmp full=y log=u01import.log
Connected to: Oracle8 Enterprise Edition Release 8.0.4.0.0 - Production
PL/SQL Release 8.0.4.0.0 - Production
Export file created by EXPORT:V08.00.05 via conventional path
. importing GXMISDBAs objects into GXMISDBA
. . importing table "AAAAA" 0 rows imported
. . importing table "EVT_CARRIER_CONFIGURATION" 0 rows imported
. . importing table "TBL_AJ_STK" 331 rows imported
IMP-00017: following statement failed with ORACLE error 2437:
"ALTER TABLE "TBL_KJ_JLRY" ADD CONSTRAINT "PK_TBL_KJ_JLRY" PRIMARY KEY ("FLD_KJ_JLRY_BH","FLD_KJ_JLRY_XM") USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE (INITIAL 10240 NEXT 10240 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 50 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)"
"ENABLE NOVALIDATE"
IMP-00003: ORACLE error 2437 encountered
ORA-02437: cannot enable (GXMISDBA.PK_TBL_KJ_JLRY) - primary key violated
.
.
.
Import terminated successfully with warnings.
数据导入出现20多个以上类似错误,后分析其中报错的"TBL_AJ_STK"表,发现"FLD_KJ_JLRY_XM"字段值(关键字组成之一)为中文字符而在Digital Unix服务器Oracle数据库中"FLD_KJ_JLRY_XM"字段值显示的为"????"(在客户端用Oracle Sql Plus查看),从而造成关键字冲突。
在客户端Oracle Sql Plus对某行显示"????"的字段值进行修改,如改成中文值”测试”,提交后,用SQL语句查看,刚修改的行中显示"????"的字段值变成了”测试”,这说明了Digital UNIN服务器上的Oracle数据集可以存储中文字符,但Oracle 8.0.4 for Digital UNIN的导入工具imp未能将Oracle 8.0.5 for Windows NT imp80导出的中文数据进行转换。
4.查看字符集参数
4.1查看Oracle 8.0.5 for Windows NT props $内容
SQL> connect sys/change_on_install
SQL> col value $ format a40
SQL> select name,value $ from props $;
NAMEVALUE $
---------------------------------------
DICT.BASE 2
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS.,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-YY
NLS_DATE_LANGUAGE AMERICAN
NLS_CHARACTERSET ZHS16GBK
NLS_SORTBINARY
NLS_NCHAR_CHARACTERSETZHS16GBK
NLS_RDBMS_VERSION 8.0.5.0.0
GLOBAL_DB_NAMEORACLE.WORLD
EXPORT_VIEWS_VERSION7
已选择15行。
4.2查看Oracle 8.0.4 for Digital UNIN 的props $内容
SQL> connect sys/change_on_install
SQL> col value $ format a40
SQL> select name,value $ from props $;
NAMEVALUE $
---------------------------------------
DICT.BASE 2
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-YY
NLS_DATE_LANGUAGE AMERICAN
NLS_CHARACTERSET ZHS16CGB231280
NLS_SORT BINARY
NLS_NCHAR_CHARACTERSET ZHS16CGB231280
NLS_RDBMS_VERSION 8.0.4.0.0
GLOBAL_DB_NAME ORCL.WORLD
EXPORT_VIEWS_VERSION7
15 rows selected.
发现Oracle 8.0.4 for Digital UNIN 采用了Oracle在Digital Unix环境下建议的中文字符集ZHS16CGB231280,两者的字符集不同,于是本人就在Digital UNIN服务器上重新安装Oracle,选择了与NT上同样的字符集ZHS16GBK(中国简体汉字16位国标库)。安装完成后,通过查看props $的内容,确认了Oracle 8.0.4 for Digital UNIN和Oracle 8.0.5 for Windows NT的字符集一致。于是用Oracle 8.0.4 for Digital UNIN的导入工具imp重新进行数据导入,但还是报同样的错误,问题还未得到解决。
5.问题解决办法
后来本人发现在Oracle 8.0.5 for Windows NT的服务器(或装有Oracle 8.0.5 for windows 95/98的工作站)上直接用Oracle 8.0.5 for Windows NT的导入工具imp80远程对Oracle 8.0.4 for Digital UNIN数据库进行数据导入,问题竟得到解决。
5.1在NT的服务器上,修改tnsnames.ora(或通过Oracle Net8 Easy config)设置数据库连接字符串gxmis(可自行设定)指向Oracle 8.0.4 for Digital UNIN服务器。
5.2在NT的服务器上进行数据远程导入
c:>imp80 gxmisdba/manager@gxmis file=c:expdat.dmpfull=y log=c:import.log
已连接到:Oracle8 Enterprise Edition Release 8.0.4.0.0 - Production
PL/SQL Release 8.0.4.0.0 - Production
经由常规路径导出由EXPORT:V08.00.05创建的文件
. 正在将GXMISDBA的对象导入到 GXMISDBA
. . 正在导入表 "AAAAA" 0行被导入
. . 正在导入表 "EVT_CARRIER_CONFIGURATION" 0行被导入
. . 正在导入表 "TBL_AJ_AGKS" 331行被导入
.
.
.
准备启用约束条件...
成功终止导入
5.3把Oracle 8.0.4 for Digital UNIN字符集重新又改成ZHS16CGB231280,进行数据远程导入测试,数据也同样地导入成功。说明ZHS16CGB231280字符集可以兼容ZHS16GBK字符集。
6.经验总结
6.1在Oracle 8.0.4 for Digital UNIN服务器上(字符集ZHS16GBK)用8.0.4 for Digital UNIN的导出工具exp将已正常(即可存储和显示中文)的数据库导出。
$ exp gxmisdba/manager file=/u01/expdat.dmp log=/u01/export.log
显示成功导出。
在用Oracle 8.0.4 for Digital UNIN的导入工具imp进行导入
$imp gxmisdba/manager file=/u01/expdat.dmp full=y log=u01import.log
错误又重现。
6.2在NT服务器上通过ftp命令将在Oracle 8.0.4 for Digital UNIN服务器上刚导出的输出转存二进制文件expdat.dmp下载至NT服务器上,用imp80进行远程导入。
c:>imp80 gxmisdba/manager@gxmis file=c:expdat.dmp full=y log=c:import.log
已连接到:Oracle8 Enterprise Edition Release 8.0.4.0.0 – Production
PL/SQL Release 8.0.4.0.0 – Production
IMP-00016: 不支持要求的字符集转换(从类型1到852)
IMP-00000: 未成功终止导入
6.3在NT服务器上对Digital UNIN服务器上的数据进行远程导出(备份)
c:>exp80 gxmisdba/manager@gxmis file=c:expdat.dmp log=c:export.log
显示成功导出。再进行远程导入
c:>imp80 gxmisdba/manager@gxmis file=c:expdat.dmp full=y log=c:import.log
显示成功导入。通过客户端Oracle Sql Plus查看中文显示正常。
从而说明在Oracle 8.0.4 for Digital UNIN服务器上对含有中文的数据库的数据移植、备份、数据恢复不要用Oracle 8.0.4 for Digital UNIN本身自带的导入导出工具imp,exp,应使用能进行中文导入导出的工具,如imp80,exp80。