匯出/匯入與字元集
進行資料的匯入匯出時,我們要注意關於字元集的問題。在EXP/IMP過程中我們需要注意四個字元集的參數:匯出端的用戶端字元集,匯出端資料庫字元集,匯入端的用戶端字元集,匯入端資料庫字元集。
我們首先需要查看這四個字元集參數。
查看資料庫的字元集的資訊:
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 TZH:TZM
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZH:TZM
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_NCHAR_CHARACTERSET ZHS16GBK
NLS_RDBMS_VERSION 8.1.7.4.1
NLS_CHARACTERSET:ZHS16GBK是當前資料庫的字元集。
我的windows oracle編碼為:
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_CHARACTERSET ZHS16GBK
我們再來查看用戶端的字元集資訊:
用戶端字元集的參數NLS_LANG=_< territory >.
language:指定oracle訊息使用的語言,日期中日和月的顯示。
Territory:指定貨幣和數位格式,地區和計算星期及日期的習慣。
Characterset:控制用戶端應用程式使用的字元集。通常設定或等於用戶端的字碼頁。或者對於unicode應用設為UTF8。
在windows中,查詢和修改NLS_LANG可在註冊表中進行:
HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\HOMExx\
xx指存在多個Oracle_HOME時的系統編號。
我這裡的windows預設為:
windows Client:
NLS_LANG SIMPLIFIED CHINESE_CHINA.ZHS16GBK
在Linux redhat5中:
[oracle@ucit ~]$ cd 注意:cd 後是空格沒有任何內容
[oracle@ucit ~]$ vi .bash_profile
加上:
export NLS_LANG="Simplified Chinese_China".ZHS16GBK 注意:四個端的參數編碼要一致
然後使用:env|grep NLS_LANG看正確沒有
在unix中:
$ env|grep NLS_LANG
NLS_LANG=simplified chinese_china.ZHS16GBK
修改可用:
$ export NLS_LANG=AMERICAN_AMERICA.UTF8
通常在匯出時最好把用戶端字元集設定得和資料庫端相同。當進行資料匯入時,主要有以下兩種情況:
(1) 來源資料庫和目標資料庫具有相同的字元集設定。
這時,只需設定匯出和匯入端的用戶端NLS_LANG等於資料庫字元集即可。
(2) 來源資料庫和目標資料庫字元集不同。
先將匯出端用戶端的NLS_LANG設定成和匯出端的資料庫字元集一致,匯出資料,然後將匯入端用戶端的NLS_LANG設定成和匯出端一致,匯入資料,這樣轉換隻發生在資料庫端,而且只發生一次。
這種情況下,只有當匯入端資料庫字元集為匯出端資料庫字元集的嚴格超集時,資料才能完全導成功,否則,可能會有資料不一致或亂碼出現。
不同版本的EXP/IMP問題
一般來說,從低版本匯入到高版本問題不大,麻煩的是將高版本的資料匯入到低版本中,在Oracle9i之前,不同版本Oracle之間的EXP/IMP可以通過下面的方法來解決:
1、在高版本資料庫上運行底版本的catexp.sql;
2、使用低版本的EXP來匯出高版本的資料;
3、使用低版本的IMP將資料庫匯入到低版本資料庫中;
4、在高版本資料庫上重新運行高版本的catexp.sql指令碼。
但在9i中,上面的方法並不能解決問題。如果直接使用低版本EXP/IMP會出現如下錯誤:
EXP-00008: orACLE error %lu encountered
orA-00904: invalid column name
這已經是一個公布的BUG,需要等到Oracle10.0才能解決,BUG號為2261722,你可以到METALINK上去查看有關此BUG的詳細資料。
BUG歸BUG,我們的工作還是要做,在沒有Oracle的支援之前,我們就自己解決。在Oracle9i中執行下面的SQL重建exu81rls視圖即可。
Create or REPLACE view exu81rls
(objown,objnam,policy,polown,polsch,polfun,stmts,chkopt,enabled,spolicy)
AS select u.name, o.name, r.pname, r.pfschma, r.ppname, r.pfname,
decode(bitand(r.stmt_type,1), 0,'', 'Select,')
|| decode(bitand(r.stmt_type,2), 0,'', 'Insert,')
|| decode(bitand(r.stmt_type,4), 0,'', 'Update,')
|| decode(bitand(r.stmt_type,8), 0,'', 'Delete,'),
r.check_opt, r.enable_flag,
DECODE(BITAND(r.stmt_type, 16), 0, 0, 1)
from user$ u, obj$ o, rls$ r
where u.user# = o.owner#
and r.obj# = o.obj#
and (uid = 0 or
uid = o.owner# or
exists ( select * from session_roles where role='Select_CATALOG_ROLE')
)
/
grant select on sys.exu81rls to public;
/
可以跨版本的使用EXP/IMP,但必須正確地使用EXP和IMP的版本:
1、總是使用IMP的版本匹配資料庫的版本,如:要匯入到817中,使用817的IMP工具。
2、總是使用EXP的版本匹配兩個資料庫中最低的版本,如:從9201往817中匯入,則使用817版本的EXP工具。