Oracle資料庫字符集問題解析(轉)

wangkxxe發表於2009-06-26
Oracle資料庫字符集問題解析

經常看到一些朋友問ORACLE字符集方面的問題,我想以迭代的方式來介紹一下。

第一次迭代:掌握字符集方面的基本概念。
有些朋友可能會認為這是多此一舉,但實際上正是由於對相關基本概念把握不清,才導致了諸多問題和疑問。
首先是字符集的概念。
我們知道,電子計算機最初是用來進行科學計算的(所以叫做“計算機”),但隨著技術的發展,還需要計算機進行其它方面的應用處理。這就要求計算機不僅能處理數值,還能處理諸如文字、特殊符號等其它資訊,而計算機本身能直接處理的只有數值資訊,所以就要求對這些文字、符號資訊進行數值編碼,最初的字符集是我們都非常熟悉的ASCII,它是用7個二進位制位來表示128個字元,而後來隨著不同國家、組織的需要,出現了許許多多的字符集,如表示西歐字元的ISO8859系列的字符集,表示漢字的GB2312-80、GBK等字符集。
字符集的實質就是對一組特定的符號,分別賦予不同的數值編碼,以便於計算機的處理。
字符集之間的轉換。字符集多了,就會帶來一個問題,比如一個字元,在某一字符集中被編碼為一個數值,而在另一個字符集中被編碼為另一個數值,比如我來創造兩個字符集demo_charset1與demo_charset2,在demo_charset1中,我規定了三個符號的編碼為:A(0001),B(0010),?(1111);而在demo_charset2中,我也規定了三個符號的編碼為:A(1001),C(1011),?(1111),這時我接到一個任務,要編寫一個程式,負責在demo_charset1與demo_charset2之間進行轉換。由於知道兩個字符集的編碼規則,對於demo_charset1中的0001,在轉換為demo_charset2時,要將其編碼改為1001;對於demo_charset1中的1111,轉換為demo_charset2時,其數值不變;而對於demo_charset1中的0010,其對應的字元為B,但在demo_charset2沒有對應的字元,所以從理論上無法轉換,對於所有這類無法轉換的情況,我們可以將它們統一轉換為目標字符集中的一個特殊字元(稱為“替換字元”),比如在這裡我們可以將?作為替換字元,所以B就轉換為了?,出現了資訊的丟失;同樣道理,將demo_charset2的C字元轉換到demo_charset1時,也會出現資訊丟失。
所以說,在字符集轉換過程中,如果源字符集中的某個字元在目標字符集中沒有定義,將會出現資訊丟失。
資料庫字符集的選擇。
我們在建立資料庫時,需要考慮的一個問題就是選擇什麼字符集與國家字符集(透過create database中的CHARACTER SET與NATIONAL CHARACTER SET子句指定)。考慮這個問題,我們必須要清楚資料庫中都需要儲存什麼資料,如果只需要儲存英文資訊,那麼選擇US7ASCII作為字符集就可以;但是如果要儲存中文,那麼我們就需要選擇能夠支援中文的字符集(如ZHS16GBK);如果需要儲存多國語言文字,那就要選擇UTF8了。
資料庫字符集的確定,實際上說明這個資料庫所能處理的字元的集合及其編碼方式,由於字符集選定後再進行更改會有諸多的限制,所以在資料庫建立時一定要考慮清楚後再選擇。
而我們許多朋友在建立資料庫時,不考慮清楚,往往選擇一個預設的字符集,如WE8ISO8859P1或US7ASCII,而這兩個字符集都沒有漢字編碼,所以用這種字符集儲存漢字資訊從原則上說就是錯誤的。雖然在有些時候選用這種字符集好象也能正常使用,但它會給資料庫的使用與維護帶來一系列的麻煩,在後面的迭代過程中我們將深入分析。
客戶端的字符集。
有過一些Oracle使用經驗的朋友,大多會知道透過NLS_LANG來設定客戶端的情況,NLS_LANG由以下部分組成:NLS_LANG=_.,其中第三部分的本意就是用來指明客戶端作業系統預設使用的字符集。所以按正規的用法,NLS_LANG應該按照客戶端機器的實際情況進行配置,尤其對於字符集一項更是如此,這樣Oracle就能夠在最大程度上實現資料庫字符集與客戶端字符集的自動轉換(當然是如果需要轉換的話)。
總結一下第一次迭代的重點:
字符集:將特定的符號集編碼為計算機能夠處理的數值;
字符集間的轉換:對於在源字符集與目標字符集都存在的符號,理論上轉換將不會產生資訊丟失;而對於在源字符集中存在而在目標字符集中不存在的符號,理論上轉換將會產生資訊丟失;
資料庫字符集:選擇能夠包含所有將要儲存的資訊符號的字符集;
客戶端字符集設定:指明客戶端作業系統預設使用的字符集。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12801008/viewspace-607653/,如需轉載,請註明出處,否則將追究法律責任。

相關文章