oracle 編碼問題|編碼處理|編碼設置

關於ORACLE數據庫中漢字顯示亂碼問題的探討

1   引言

     ORACLE數據庫作爲業界領先的數據庫產品,近年來在國內大中型企業中得到了廣泛的應用。雖然ORACLE數據庫產品本身在本地化方面已做得相當成熟,但還是有不少用戶反應漢字顯示亂碼的問題。如對同一數據庫不同的用戶對同一表中的username查詢卻得出了不同的結果: “ORACLE??????”和“ORACLE中國有限公司”,顯然結果中將中文字符顯示爲亂碼,那麼爲什麼呢?字符集的設置不當是影響ORACLE數據庫漢字顯示的關鍵問題。

2   關於字符集

     字符集是ORACLE爲適應不同語言文字顯示而設定的。用於漢字顯示的字符集主要有ZHS16CGB231280、ZHS16GBK、US7ASCII和UTF-8等。字符集同時存在於服務器端和客戶端。服務器端字符集是在安裝ORACLE時指定的,字符集登記信息存儲在ORACLE數據庫字典的V$NLS_PARAMETERS表中;而客戶端字符集是在系統註冊表(WINDOWS系統)或在用戶的環境變量(UNIX系統)中設定的。

3   字符集的構成與設定

     字符集的構成與設定方式分爲客戶端與服務器端兩種:
     (1)客戶端字符集的構成與設定。客戶端的字符集是由當前用戶的環境變量NLS_LANG設定的。環境變量NLS_LANG的構成:
NLS_LANG=language_territory.charset     
其中,
language   指定服務器消息的語言
territory    指定服務器的日期和數字格式
charset     指定字符集
三個成分可以任意組合,例如:
AMERICAN_AMERICA.US7SCII
SIMPLIFIED CHINESE_CHINA.ZHS16GBK
AMERICAN_AMERICA. ZHS16GBK
     客戶端字符集的設定方法針對不同操作系統設定方法稍有不同:WINDOWS系統是在註冊表項:HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\HOME0\NLS_LANG中設定;UNIX系統是在當前用戶的環境變量中設定,如在當前用戶的profile文件中增加一行如下代碼:
NLS_LANG=SIMPLIFIED Chinese_CHINA.ZHS16GBK;export NLS_LANG
     (2)服務端字符集的構成與設定。服務端字符集的構成體現在數據字典表V$NLS_PARAMETERS的NLS_LANGUAGE、NLS_TERRITORY、NLS_CHARACTERSET三項取值上,其中NLS_CHARACTERSET的取值就是具體的數據庫字符集。
如利用查詢語句SQL>SELECT * FROM V$NLS_PARAMETERS;
可得到如下結果:
PARAMETER                    VALUE
------------------------------------------------------------
NLS_LANGUAGE            SIMPLIFIED CHINESE
NLS_TERRITORY                 CHINA
……
NLS_CHARACTERSET            ZHS16GBK
……
     即當前數據庫使用的字符集是ZHS16GBK。
     數據庫服務端的字符集是在創建數據時設定的。但可通過如下方法對已設定的字符集進行修改:
     方法一:重建數據庫。建立數據庫時將數據庫的字符集設定爲所需字符集。
     方法二:修改SYS.PROPS$表。即用SYS用戶登陸ORACLE後,利用下面語句修改相應的字符集並提交:
SQL>UPDATE PROPS$ SET VALUE$=’ZHS16GBK‘
WHERE NAME=’NLS_CHARACTERSET’;
SQL>COMMIT;
     通過此種方法來更改數據庫字符集,只對更改後的數據有效,即數據庫中原來的數據仍以原字符集被存儲。
     另外,有的還利用CREATE DATABASE CHARACTER SET ZHS16GBK命令暫時的修改字符集,當重啓數據庫後,數據庫字符集將恢復原來的字符集。

4   常見的漢字亂碼問題及解決方案

     要在客戶端正確顯示ORACLE數據庫中的漢字信息,首先必須使客戶端的字符集與服務器端的字符集一致;其次是加載到ORACLE數據庫的數據字符集必須與服務器字符集一致。據此,漢字顯示亂碼的問題大致可以分爲以下幾種情況:
     (1)客戶端字符集與服務器端字符集不同,服務器端字符集與加載數據字符集一致。這種情況是最常見的,只要把客戶端的字符集設置正確即可。具體解決方案:
      第一步:查詢V$NLS_PARAMETERS得到服務端的字符集:
SQL>SELECT * FROM V$NLS_PARAMETERS;
   第二步:根據服務端的字符集設定客戶端的字符集,設定方法參見客戶端的字符集的設定方式。
以UNIX系統爲例,可在當前用戶的profile文件中增加如下兩行:
     NLS_LANG=SIMPLIFIED Chinese_CHINA.ZHS16GBK
     export NLS_LANG
     (2)客戶端字符集與服務器端字符集相同,服務器端字符集與加載數據字符集不一致。這種情況一般發生在ORACLE版本升級或重新安裝數據庫時選擇了與原來數據庫不同的字符集,而恢復加載的備份數據仍是按原字符集卸出的場合。另一種情況是加載從其它使用不同字符集的ORACLE數據庫卸出的數據。在這兩種情況中,不管客戶端字符集與服務器端字符集是否一致都無法正確顯示漢字。具體解決方案:
     方案一:按服務端字符集的修改方法修改服務端字符集與加載數據字符集一致,然後導入數據。
     方案二:利用數據格式轉儲,避開字符集帶來的問題。即先將加載數據倒入到與其字符集一致的數據庫中,然後再將數據要麼按文本格式導出(數據量較小的情況下),要麼通過第三方工具(如POWER BUILDER,ACCESS,FOXPRO等)倒出數據,最後將倒出的數據導入到目標數據庫中。
     (3)客戶端字符集與服務器端字符集不同,服務端字符集與輸入數據字符集不同。這種情況是在客戶端字符集與服務器端字符集不一致時,從客戶端輸入了漢字信息。輸入的這些信息即便是把客戶端字符集更改正確,也無法顯示漢字。解決方案:修改客戶端字符集與服務端字符集一致後,重新輸入數據。

 

其中:

sqlplus亂碼解決

export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK (顯示英文)

export NLS_LANG="SIMPLIFIED CHINESE"_CHINA.zhs16cgb231280
                                                                                       (顯示簡體中文)

5   結束語

     根據ORACLE官方文檔的說明,一旦數據庫創建後,數據庫的字符集是不能改變的。因此,提前考慮自己的數據庫將選用哪一種字符集是十分重要的。數據庫字符集選擇的一般規則是將數據庫字符集設定爲操作系統本地字符集的一個超集,同時數據庫字符集也應該是所有客戶字符集的超集。如同樣是中文環境,在選擇ZHS16CGB231280還是ZHS16GBK時,我們更多的情況是選擇ZHS16GBK,因爲它包含了ZHS16CGB231280字符集。

參考文獻

     1 (美)JONATHAN GENNICK CAROL MCCULLOUGH-DIETER GERRIT-JAN LINKER ,譯者:趙豔勤, 劉冠英, 秦玉傑 等.《ORACLE8I DBA寶典》.電子工業出版社
     2 JASON COUCHMAN,SUDHEER MARISETTI.《OCP ORACLE9I DATABASE:FUNDAMENTALS I EXAM GUIDE》.出版社: MCGRAW-HILL
     3 ORACLE Corporation.ORACLE 9i Database Administration Fundamentas I Student Guide》
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章