理解ORACLE資料庫字符集 2

2021-04-21 21:47:09 字數 4644 閱讀 7286

三.匯入/匯出與字符集轉換

3.1 exp/imp

export 和 import 是一對讀寫oracle資料的工具。export 將 oracle 資料庫中的資料輸出到作業系統檔案中, import 把這些檔案中的資料讀到oracle 資料庫中,由於使用exp/imp進行資料遷移時,資料從源資料庫到目標資料庫的過程中有四個環節涉及到字符集,如果這四個環節的字符集不一致,將會發生字符集轉換。

exp ____________ 

_________________  _____________

|imp匯入檔案|<-|環境變數nls_lang|<-|資料庫字符集|

------------ 

----------------- 

-------------

imp 

____________ 

_________________  _____________

|imp匯入檔案|->|環境變數nls_lang|->|資料庫字符集|

------------ 

----------------- 

-------------

四個字符集是

(1)源資料庫字符集

(2)export過程中使用者會話字符集(通過nls_lang設定)

(3)import過程中使用者會話字符集(通過nls_lang設定)

(4)目標資料庫字符集

3.2匯出的轉換過程

在export過程中,如果源資料庫字符集與export使用者會話字符集不一致,會發生字符集轉換,並在匯出檔案的頭部幾個位元組中儲存export使用者會話字符集的id號。在這個轉換過程中可能發生資料的丟失。

例:如果源資料庫使用zhs16gbk,而export使用者會話字符集使用us7ascii,由於zhs16gbk是16位字符集,而us7ascii是7位字符集,這個轉換過程中,中文字元在us7ascii中不能夠找到對等的字元,所以所有中文字元都會丟失而變成「?? 」形式,這樣轉換後生成的dmp檔案已經發生了資料丟失。

因此如果想正確匯出源資料庫資料,則export過程中使用者會話字符集應等於源資料庫字符集或是源資料庫字符集的超集

3.3匯入的轉換過程

(1)確定匯出資料庫字符集環境

通過讀取匯出檔案頭,可以獲得匯出檔案的字符集設定

(2)確定匯入session的字符集,即匯入session使用的nls_lang環境變數

(3)imp讀取匯出檔案

讀取匯出檔案字符集id,和匯入程序的nls_lang進行比較

(4)如果匯出檔案字符集和匯入session字符集相同,那麼在這一步驟內就不需要轉換,如果不同,就需要把資料轉換為匯入session使用的字符集。可以看出,匯入資料到資料庫過程中發生兩次字符集轉換

第一次:匯入檔案字符集與匯入session使用的字符集之間的轉換,如果這個轉換過程不能正確完成,import向目標資料庫的匯入過程也就不能完成。

第二次:匯入session字符集與資料庫字符集之間的轉換。

然而,oracle8i的這種轉換只能在單位元組字符集之間進行,oracle8i匯入session不支援多位元組字符集之間的轉換,因此為了避免第一次轉換,匯入session使用的nls_lang與匯出檔案字符集相同,第二次轉換(通過sql*net)支援任何兩種字符集。以上情況在oracle9i中略有不同

四.亂碼問題

oracle在資料儲存、遷移過程中經常發生字元亂碼問題,歸根到底是由於字符集使用不當引起。下面以使用客戶端sqlplus向資料庫插入資料和匯入/匯出(exp/imp)過程為例,說明亂碼產生的原因。

4.1使用客戶端sqlplus向資料庫儲存資料

這個過程存在3個字符集設定

(1)客戶端應用字符集

(2)客戶端nls_lang引數設定

(3)伺服器端資料庫字符集(character set)設定

客戶端應用sqlplus中能夠顯示什麼樣的字元取決於客戶端作業系統語言環境(客戶端應用字符集),但在應用中錄入這些字元後,這些字元能否在資料庫中正常儲存,還與另外兩個字符集設定緊密相關,其中客戶端nls_lang引數主要用於字元資料傳輸過程中的轉換判斷。常見的亂碼大致有兩種情形:

(1)漢字變成問號「?」;

當從字符集a 轉換成字符集b時,如果轉換字元之間不存在對應關係,nls_lang使用替代字元「?」替代無法對映的字元

(2)漢字變成未知字元(雖然有些是漢字,但與原字元含義不同)

轉換存在對應關係,但字符集a 中的字元編碼與字符集b 中的字元編碼代表不同含義

4.2發生亂碼原因

亂碼產生是由於幾個字符集之間轉換不匹配造成,分以下幾種情況:

(注:字符集之間如果不存在子集、超集對應關係時的情況不予考慮,因為這種情況下字符集之間轉換必產生亂碼)

1)伺服器端資料庫字符集與客戶端應用字符集相同,與客戶端nls_lang引數設定不同

如果客戶端nls_lang字符集是其它兩種字符集的子集,轉換過程將出現亂碼。

解決方法:將三種字符集設定成同一字符集,或nls_lang字符集是其它兩種字符集的超集

2)伺服器端資料庫字符集與客戶端nls_lang引數設定相同,與客戶端應用字符集不同

如果客戶端應用字符集是其它兩種字符集的超集時,轉換過程將出現亂碼,但對於單位元組編碼儲存中文問題,可參看本文第5章節的分析

3)客戶端應用字符集、客戶端nls_lang引數設定、伺服器端資料庫字符集互不相同

此種情況較為複雜,但三種字符集之間只要有不能轉換的字元,則必產生亂碼

4.3匯入/匯出過程出現亂碼原因

這個過程存在4個字符集設定,在3.1章節中已分析

(1)源資料庫字符集

(2)exp過程中nls_lang引數

(3)imp過程中nls_lang引數

(4)目標資料庫字符集

出現亂碼原因

1)當源資料庫字符集不等於exp過程中nls_lang引數,且源資料庫字符集是exp過程中nls_lang的子集,才能保證匯出檔案正確,其他情況則匯出檔案字元亂碼

2)exp過程中nls_lang字符集不等於imp過程中nls_lang字符集,且exp過程中nls_lang字符集是imp過程中nls_lang字符集的子級, 才能保證第一次轉換正常,否則第一次轉換中出現亂碼。

3)如果第一次轉換正常,imp過程中nls_lang字符集是目標資料庫字符集的子集或相同,才能保證第二次轉換正常,否則則第二次轉換中出現亂碼

五.單位元組編碼儲存中文問題

由於歷史的原因,早期的oracle沒有中文字符集(如oracle6、oracle7、oracle7.1),但有的使用者從那時起就使用資料庫了,並用us7ascii字符集儲存了中文,或是有的使用者在建立資料庫時,不考慮清楚,隨意選擇乙個預設的字符集,如we8iso8859p1或us7ascii,而這兩個字符集都沒有漢字編碼,雖然有些時候選用這種字符集好象也能正常使用,但用這種字符集儲存漢字資訊從原則上說就是錯誤的,它會給資料庫的使用與維護帶來一系列的麻煩。

正常情況下,要將漢字存入資料庫,資料庫字符集必須支援中文,而將資料庫字符集設定為us7ascii等單位元組字符集是不合適的。us7ascii字符集只定義了128個符號,並不支援漢字。另外,如果在sql*plus中能夠輸入中文,作業系統預設應該是支援中文的,但如果在nls_lang中的字符集設定為us7ascii,顯然也是不正確的,它沒有反映客戶端的實際情況。但在實際應用中漢字顯示卻是正確的,這主要是因為oracle檢查資料庫與客戶端的字符集設定是同樣的,那麼資料在客戶與資料庫之間的訪問過程中將不發生任何轉換,但是這實際上導致了資料庫標識的字符集與實際存入的內容是不相符的。而在select的過程中,oracle同樣檢查發現資料庫與客戶端的字符集設定是相同的,所以它也將存入的內容原封不動地傳送到客戶端,而客戶端作業系統識別出這是漢字編碼所以能夠正確顯示。

在這個例子中,資料庫與客戶端都沒有設定成中文字符集,但卻能正常顯示中文,從應用的角度看好象沒問題。然而這裡面卻存在著極大的隱患,比如在應用length或substr等字串函式時,就可能得到意外的結果。

對於早期使用us7ascii字符集資料庫的資料遷移到oracle8i/9i中(使用zhs16gbk),由於原始資料已經按照us7ascii格式儲存,對於這種情況,可以通過使用oracle8i的匯出工具,設定匯出字符集為us7ascii,匯出後使用ultraedit等工具開啟dmp檔案,修改第

二、三字元,修改 0001 為0354,這樣就可以將us7ascii字符集的資料正確匯入到zhs16gbk的資料庫中。

六.結束語

為了避免在資料庫遷移過程中由於字符集不同導致的資料損失,oracle提供了字符集掃瞄工具(character set scanner),通過這個工具我們可以測試在資料遷移過程中由於字符集轉換可能帶來的問題,然後根據測試結果,確定資料遷移過程中最佳字符集解決方案。

參考文獻

[1]biju thomas , bob bryla

《oracle9i dba基礎i 學習指南》電子工業出版社

2002

oracle 資料庫的字符集(2)

2 資料庫的字符集 字符集在建立資料庫時指定,在建立後通常不能更改,所以在建立資料庫時能否選擇乙個正確的字符集就顯得尤為重要。在建立資料庫時,我們可以指定字符集 character set 和國家字符集 national character set 字符集用來儲存 char,varchar2,clo...

oracle 資料庫字符集

oracle全球支援 即globalization support 允許我們使用本地語言和格式來儲存和檢索資料。通過全球支援,oracle可以支援多種語言及字符集,得以展示資料庫的強大魅力。1 字符集的基本知識 如果從頭說起,字符集最早的編碼方案來自於與ascii.這也是我們最常見的編碼方式。該方案...

oracle資料庫字符集

一 什麼是oracle字符集 oracle字符集是乙個位元組資料的解釋的符號集合,有大小之分,有相互的包容關係。oracle 支援國家語言的體系結構允許你使用本地化語言來儲存,處理,檢索資料。它使資料庫工具,錯誤訊息,排序次序,日期,時間,貨幣,數字,和日曆自動適應本地化語言和平台。影響oracle...