Export: Release11.1.0.6.0 - Production on 星期一 9月 2710:39:052010 Copyright (c) 1982, 2007, Oracle. All rights reserved. Username: Password: [oracle@wapdb ~]$ grep nls exp.log open("/opt/oracle/product/11.1.0/nls/data/lx1boot.nlb", O_RDONLY) = 3 open("/opt/oracle/product/11.1.0/nls/data/lx00023.nlb", O_RDONLY) = 3 open("/opt/oracle/product/11.1.0/nls/data/lx20354.nlb", O_RDONLY) = 3 open("/opt/oracle/product/11.1.0/nls/data/lx10035.nlb", O_RDONLY) = 3 open("/opt/oracle/product/11.1.0/nls/data/lx20001.nlb", O_RDONLY) = 3 open("/opt/oracle/product/11.1.0/nls/data/lx00001.nlb", O_RDONLY) = 3 open("/opt/oracle/product/11.1.0/nls/data/lx10001.nlb", O_RDONLY) = 3 open("/opt/oracle/product/11.1.0/nls/data/lx207d0.nlb", O_RDONLY) = 9在執行導出數據操作時(shí),導出使用的字符集將會(huì )記錄在導出的DMP文件中,當文件導入時(shí),將會(huì )檢查導出時(shí)使用的字符集設置,如果這個(gè)字符集不同于導入客戶(hù)端的NLS_LANG設置,字符集將根據導入客戶(hù)端NLS_LANG設置進(jìn)行轉換,如果必要,在數據插入數據庫之前還會(huì )進(jìn)行進(jìn)一步轉換。所以通常在執行導出操作時(shí),最好把客戶(hù)端字符集設置得和數據庫相同,這樣可以避免在導出時(shí)發(fā)生不必要的數據轉換,導出文件將和數據庫具有相同的字符集,數據得以完好備份。即使將來(lái)會(huì )把導出文件導入到不同字符集的數據庫中,這樣做也可以把轉換延緩至導入時(shí)刻。3.4 導入導出及字符轉換 當進(jìn)行數據導入時(shí),主要存在以下兩種情況。· 源數據庫和目標數據庫具有相同字符集設置。這時(shí),只需要設置NLS_LANG等于數據庫字符集即可導入(前提是,導出使用的是和源數據庫相同字符集,即三者相同)· 源數據庫和目標數據庫字符集不同。如果導出時(shí)候使用的NLS_LANG是和源數據庫相同的字符集,那么導入時(shí)就可以設置客戶(hù)端NLS_LANG等于導出時(shí)使用的字符集,這樣轉換只發(fā)生在數據庫端,而且只發(fā)生一次。例如進(jìn)行從WE8MSWIN1252到UTF8的轉換,以下是一個(gè)常用的參考步驟:(1)使用NLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252導出數據庫。這時(shí)創(chuàng )建的導出文件包含WE8MSWIN1252的數據。(2)導入時(shí)使用NLS_LANG=AMERICAN_AMERICA.WE8MSWIN1252。這時(shí)轉換僅發(fā)生在insert數據到UTF8的數據庫中。以上假設的轉換只在目標數據庫字符集是源數據庫字符集的超集時(shí)才能轉換。如果不同,一般就需要進(jìn)行一些特殊的處理。再來(lái)看一下執行導入時(shí)Oracle的一些判斷和處理過(guò)程(以Oracle 8i為例):(1)首先確定導出數據庫字符集環(huán)境。通過(guò)讀取導出文件頭,可以獲得導出文件的字符集設置(2)確定導入session的字符集,即導入Session使用的NLS_LANG環(huán)境變量。(3)通過(guò)IMP讀取導出文件。讀取導出文件字符集ID,和導入進(jìn)程的NLS_LANG進(jìn)行比較。(4)如果導出文件字符集和導入Session字符集相同,那么在這一步驟內就不需要轉換,如果不同,就需要把數據轉換為導入Session使用的字符集。然而這種轉換只能在單byte字符集之間進(jìn)行。來(lái)看一個(gè)測試,首先設置導入session NLS_LANG為US7ASCII:E:\nls2>set NLS_LANG=AMERICAN_AMERICA.US7ASCII執行導入操作:E:\nls2>e:\oracle\ora8i\bin\imp eygle/eygle file=Sus7ascii-Cus7ascii-exp817.dmp fromuser=eygle touser=eygle tables=test這個(gè)導出文件是從US7ASCII數據庫導出,導出客戶(hù)端NLS_LANG也是US7ASCII:Import: Release8.1.7.1.1 - Production on Fri Nov 700:59:222003 (c) Copyright 2000Oracle Corporation. All rights reserved.
Connected to: Oracle8i EnterpriseEditionRelease8.1.7.1.1 - Production With the Partitioning option JServer Release8.1.7.1.1 - Production這時(shí)導入,在DMP文件和NLS_LANG之間不需要進(jìn)行字符集轉換,但是由于導出文件字符集和數據庫字符集(ZHS16GBK)不同,在數據導入Server時(shí)需要進(jìn)行轉換。Export file created by EXPORT:V08.01.07 via conventional path import done in US7ASCII character setand ZHS16GBK NCHARcharacterset importserver uses ZHS16GBK characterset (possible charset conversion) exportserver uses UTF8 NCHARcharacterset (possible ncharset conversion) . . importing table"TEST"2rows imported Importterminated successfully without warnings.(5)對于多Byte字符集的導入(如UTF8),需要設置導入Session字符集和導出字符集相同,否則就會(huì )遇到以下錯誤:IMP-16 "Required character set conversion (type %lu to %lu) not supported"。E:\nls2>set NLS_LANG=AMERICAN_AMERICA.ZHS16GBK導入Session字符集設置為ZHS16GBK,導入US7ASCII的導出文件:E:\nls2>e:\oracle\ora8i\bin\imp eygle/eygle file=Sus7ascii-Cus7ascii-exp817.dmp fromuser=eygle touser=eygle
Import: Release 8.1.7.1.1 - Production on Fri Nov 7 00:38:55 2003 (c) Copyright 2000 Oracle Corporation. All rights reserved.
Connected to: Oracle8i Enterprise Edition Release 8.1.7.1.1 - Production With the Partitioning option JServer Release 8.1.7.1.1 - Production
IMP-00016: required character set conversion (type 1 to 852) not supported IMP-00000: Import terminated unsuccessfully在從導出文件US7ASCII到導入NLS_LANG設置為ZHS16GBK的過(guò)程中,不支持單Byte字符集向多Byte轉換,報出以上錯誤。(6)導入Session字符集應該是導出字符集的超集,否則,專(zhuān)有的字符將難以正確轉換。(7)當數據轉換為導入Session字符集設置以后,如果導入Session字符集仍然不同于目標數據庫字符集,那么數據在插入數據庫之前還需要進(jìn)行最后一步轉換,這要求目標數據庫字符集是導入session字符集的超集,否則某些專(zhuān)有字符將不能正常轉換。繼續看上面的兩個(gè)過(guò)程,這里有這樣兩個(gè)原則:· 如果NLS_LANG的設置和數據庫相同,那么數據(在傳輸過(guò)程中當然是二進(jìn)制碼)不經(jīng)過(guò)轉換就直接插入數據庫中。· 如果NLS_LANG的設置和數據庫不同,那么數據需要轉換后才能插入數據庫中。再回頭來(lái)看上面的第一個(gè)例子:Export file created by EXPORT:V08.01.07 via conventional path import done in US7ASCII character setand ZHS16GBK NCHARcharacterset importserver uses ZHS16GBK characterset (possible charset conversion) exportserver uses UTF8 NCHARcharacterset (possible ncharset conversion) . . importing table"TEST"2rows imported Importterminated successfully without warnings.這時(shí)候經(jīng)過(guò)第一步轉換后的數據,US7ASCII到ZHS16GBK丟失首位,原樣插入數據庫,可以看到這時(shí)數據庫中存放的就是錯誤的字符(在后面部分做了詳細的轉換):E:\nls2>sqlplus eygle/eygle Connected to:Oracle8i Enterprise Edition Release 8.1.7.1.1 - Production With the Partitioning option JServer Release 8.1.7.1.1 - Production
SQL> select * from test; NAME -------------------- 2bJT test對于Oracle 10g開(kāi)始引入得數據泵(expdp/impdp)工具,不再存在以前EXP/IMP的字符集轉換問(wèn)題,expdp/impdp實(shí)際上是通過(guò)工具在數據庫服務(wù)器上提交一個(gè)任務(wù),真正的導出及導入操作都是在數據庫服務(wù)器上完成的,這就簡(jiǎn)化了Oracle的數據轉儲工作。