http://www.nsshell.com/info/info.php?sessid=&infoid=19Oracle数据库移植时字符集问题的解决 (2004-02-17 09:11)
来源:Oracle数据库在线
对于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导出的中文数据进行转换。
来源:Oracle数据库在线
对于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.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$;
NAME VALUE$
---------------------------------------
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_SORT BINARY
NLS_NCHAR_CHARACTERSET ZHS16GBK
NLS_RDBMS_VERSION 8.0.5.0.0
GLOBAL_DB_NAME ORACLE.WORLD
EXPORT_VIEWS_VERSION 7
已选择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$;
NAME VALUE$
---------------------------------------
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_VERSION 7
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。 江西思创数码科技有限公司 江恭和
1。SQL>CONNECT SYSTEM/MANAGER SQL>UPDATE SYS.PROPS$ SET VALUE$='WE8ISO8859P1' WHERE NAME LIKE 'NLS_CHAR%';
2.修改注册表,NLS_LANG的值为AMERICAN_AMERICA.WE8ISO8859P1
3。重新启动数据库。
IMP USER/PA WD FILE=A。DMP FULL=Y LOG = A.TXT
ok!
--------------------------------------------------------------------------------------------------
1. 2服务器指定字符集与客户字符集相同,与加载数据字符集不一致。 ---- 这类问题一般发生在ORACLE版本升级或重新安装系统时选择了与原来服务器端不同的字符集,而恢复加载的备份数据仍是按原字符集卸出的场合,以及加载从其它使用不同字符集的ORACLE数据库卸出的数据的情况。这两种情况中,不管服务器端和客户端字符集是否一致都无法显示汉字。解决办法见2.2。 2.2 强制加载数据字符集与服务器端字符集一致 ---- 假设要加载数据从原ORACLE数据库卸出时的字符集为US7ASCII,当前ORACLE服务器字符集为WE8ISO8859P1。 ---- 下面提供三种解决方法: ---- (1) 服务器端重新安装ORACLE ---- 在重新安装ORACLE 时选择与原卸出数据一致的字符集(本例为US7ASCII)。 ---- 加载原卸出的数据。 ---- 这种情况仅仅使用于空库和具有同一种字符集的数据。 ---- (2)强行修改服务器端ORACLE当前字符集 ---- 在用imp命令加载数据前,先在客户端用sql*plus登录system DBA用户,执行下列SQL语句进行当前ORACLE数据库字符集修改: SQL > create database character set US7ASCII
* create database character set US7ASCII
ERROR at line 1:
ORA-01031: insufficient privileges
---- 你会发现语句执行过程中,出现上述错误提示信息,此时不用理会,实际上ORACLE数据库的字符集已被强行修改为US7ASCII,接着用imp命令装载数据。等数据装载完成以后,shutdown 数据库,再startup 数据库,用合法用户登录ORACLE数据库,在sql>命令提示符下,运行select * from V$NLS_PARAMETERS,可以看到ORACLE数据库字符集已复原,这时再查看有汉字字符数据的表时,汉字已能被正确显示。 ---- (3)利用数据格式转储,避开字符集限制 ---- 这种方法主要用于加载外来ORACLE数据库的不同字符集数据。其方法如下: ---- 先将数据加载到具有相同字符集的服务器上,然后用转换工具卸出为foxbase 格式或access格式数据库,再用转换工具转入到不同字符集的ORACLE数据库中,这样就避免了ORACLE字符集的困扰。目前数据库格式转换的工具很多,象power builder5.0以上版本提供的pipeline,Microsoft Access数据库提供的数据导入/导出功能等。转换方法参见有关资料说明。.
用编辑方式打开导出的dmp文件,获取2、3字节的内容,如00 01,先把它转换为10进制数,为1,使用函数NLS_CHARSET_NAME即可获得该字符集:
SQL> select nls_charset_name(1) from dual;
NLS_CHARSET_NAME(1)
-------------------
US7ASCII
可以知道该dmp文件的字符集为US7ASCII,如果需要把该dmp文件的字符集换成ZHS16GBK,则需要用NLS_CHARSET_ID获取该字符集的编号:
SQL> select nls_charset_id('zhs16gbk') from dual;
NLS_CHARSET_ID('ZHS16GBK')
--------------------------
852
把852转换成16进制数,为354,把2、3字节的00 01换成03 54,即完成了把该dmp文件字符集从us7ascii到zhs16gbk的转化,这样,再把该dmp文件导入到zhs16gbk字符集的数据库就可以了。
你DMP文件的字符集是US7ASCII,现在ORACLE的字符集是ZHS16GBK,
第一步:修改现在操作系统的注册表HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0\把下面的一个键值NLS_LANG改为AMERICAN_AMERICA.US7ASCII
第二步修改现在ORACLE的字符集为US7ASCII:
CONNECT INTERNAL/[email protected]
shutdown immediate
startup mount
ALTER SYSTEM ENABLE RESTRICTED SESSION;
ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
ALTER SYSTEM SET AQ_TM_PROCESSES=0;
ALTER DATABASE OPEN;
update props$ set value$='US7ASCII' WHERE NAME='NLS_CHARACTERSET';
update props$ set value$='US7ASCII' WHERE NAME='NLS_NCHAR_CHARACTERSET';
SHUTDOWN IMMEDIATE
STARTUP
第三步导入数据,OK!