對於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$;
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。