關於Oracle字符集的問題

tolywang發表於2006-05-24

1。select name,value$ from props$;
2。select * from nls_database_parameters 可以查詢到對應的系統的字符集設定..
相應的將你的客戶端的nls_lang或者登錄檔項設定成對應的字符集
這樣就能看到伺服器端的字符集了
伺服器是8i 的客戶端字符集改成 AMERICAN.WE8ISO8859P1 就可以了。




影響ORACLE漢字顯示的字符集問題
中原油田研究院
康子明 等4人
---- 在國內外大中型資料庫管理系統中,把ORACLE作為資料庫管理平臺的使用者比較多。ORACLE 不論是資料庫管理能力還是安全性都是無可非議的,但是,它在漢字資訊的顯示方面著實給中國使用者帶來不少麻煩,筆者多年從事ORACLE資料庫管理,經常收到周圍使用者和外地使用者反映有關ORACLE資料庫漢字顯示問題的求援信,主要現象是把漢字顯示為不可識別的亂碼,造成原來大量資訊無法使用。本文將就這一問題產生的原因和解決辦法進行一些探討,供存在這方面問題的使用者朋友參考。

---- 1、原因分析

---- 透過對使用者反映情況的分析,發現字符集的設定不當是影響ORACLE資料庫漢字顯示的關鍵問題。那麼字符集是怎麼一會事呢?字符集是ORACLE 為適應不同語言文字顯示而設定的。用於漢字顯示的字符集主要有ZHS16CGB231280,US7ASCII,WE8ISO8859P1等。字符集不僅需在伺服器端存在,而且客戶端也必須有字符集註冊。伺服器端,字符集是在安裝ORACLE時指定的,字符集登記資訊儲存在ORACLE資料庫字典的V$NLS_PARAMETERS表中;客戶端,字符集分兩種情況,一種情況是sql*net 2.0以下版本,字符集是在windows的系統目錄下的oracle.ini檔案中登記的;另一種情況是sql*net 2.0以上(即32位)版本,字符集是在windows的系統登錄檔中登記的。要在客戶端正確顯示ORACLE 資料庫漢字資訊,首先必須使伺服器端的字符集與客戶端的字符集一致;其次是載入到ORACLE資料庫的資料字符集必須與伺服器指定字符集一致。因此,把使用者存在的問題歸納分類,產生漢字顯示異常的原因大致有以下幾種:

---- 1. 1伺服器指定字符集與客戶字符集不同,而與載入資料字符集一致。

---- 這種情況是最常見的,只要把客戶端的字符集設定正確即可,解決辦法見2.1。

---- 1. 2伺服器指定字符集與客戶字符集相同,與載入資料字符集不一致。

---- 這類問題一般發生在ORACLE版本升級或重新安裝系統時選擇了與原來伺服器端不同的字符集,而恢復載入的備份資料仍是按原字符集卸出的場合,以及載入從其它使用不同字符集的ORACLE資料庫卸出的資料的情況。這兩種情況中,不管伺服器端和客戶端字符集是否一致都無法顯示漢字。解決辦法見2.2。

---- 1.3伺服器指定字符集與客戶字符集不同,與輸入資料字符集不一致。

---- 這種情況是在客戶端與伺服器端字符集不一致時,從客戶端輸入了漢字資訊。輸入的這些資訊即便是把客戶端字符集更改正確,也無法顯示漢字。解決辦法見2.3。

---- 2.解決辦法

---- 下面將分別對上述三種情況給出解決辦法。為了敘述方便,假設客戶端使用WINDOWS95/98環境,並已成功地配置了TCP/IP協議,安裝了ORACLE的sql*net,sql*pluse產品。

---- 2.1 設定客戶端字符集與伺服器端字符集一致

---- 假設當前伺服器端使用US7ASCII字符集。

---- (1)檢視伺服器端字符集

---- 透過客戶端或伺服器端的sql*plus登入ORACLE的一個合法使用者,執行下列SQL語句:

SQL > select * from V$NLS_PARAMETERS
parameter value
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
…. ….
NLS_CHARACTERSET US7ASCII
NLS_SORT BINARY
NLS_NCHAR_CHARACTERSET US7ASCII

---- 從上述列表資訊中可看出伺服器端ORACLE資料庫的字符集為'US7ASCII'。

---- (2)按照伺服器端字符集對客戶端進行配置

---- 配置方法有兩種:

安裝ORACLE的客戶端軟體時指定
---- 在安裝ORACLE的客戶端產品軟體時,選擇與ORACLE服務端一致的字符集(本例為US7ASCII)即可。

修改註冊資訊的方法
---- 根據ORACLE 客戶端所選sql*net 的版本分為下列兩種情況:

---- a. 客戶端為 sql*net 2.0 以下版本

---- 進入Windows的系統目錄,編輯oracle.ini檔案,用US7ASCII替換原字符集,重新啟動計算機,設定生效。

---- b. 客戶端為 sql*net 2.0 以上版本

---- 在WIN98 下 運 行REGEDIT,第一步選HKEY_LOCAL_MACHINE,第二步選擇SOFTWARE, 第三步選擇 ORACLE, 第四步選擇 NLS_LANG, 鍵 入 與服 務 器 端 相 同 的 字 符 集(本例為:AMERICAN_AMERICAN.US7ASCII)。

---- 2.2 強制載入資料字符集與伺服器端字符集一致

---- 假設要載入資料從原ORACLE資料庫卸出時的字符集為US7ASCII,當前ORACLE伺服器字符集為WE8ISO8859P1。

---- 下面提供三種解決方法:

---- (1) 伺服器端重新安裝ORACLE

---- 在重新安裝ORACLE 時選擇與原卸出資料一致的字符集(本例為US7ASCII)。

---- 載入原卸出的資料。

---- 這種情況僅僅使用於空庫和具有同一種字符集的資料。

---- (2)強行修改伺服器端ORACLE當前字符集

---- 在用imp命令載入資料前,先在客戶端用sql*plus登入system DBA使用者,執行下列SQL語句進行當前ORACLE資料庫字符集修改:

SQL > create database character set US7ASCII
* create database character set US7ASCII
ERROR at line 1:
ORA-01031: insufficient privileges

---- 你會發現語句執行過程中,出現上述錯誤提示資訊,此時不用理會,實際上ORACLE資料庫的字符集已被強行修改為US7ASCII,接著用imp命令裝載資料。等資料裝載完成以後,shutdown 資料庫,再startup 資料庫,用合法使用者登入ORACLE資料庫,在sql>命令提示符下,執行select * from V$NLS_PARAMETERS,可以看到ORACLE資料庫字符集已復原,這時再檢視有漢字字元資料的表時,漢字已能被正確顯示。

---- (3)利用資料格式轉儲,避開字符集限制

---- 這種方法主要用於載入外來ORACLE資料庫的不同字符集資料。其方法如下:

---- 先將資料載入到具有相同字符集的伺服器上,然後用轉換工具卸出為foxbase 格式或access格式資料庫,再用轉換工具轉入到不同字符集的ORACLE資料庫中,這樣就避免了ORACLE字符集的困擾。目前資料庫格式轉換的工具很多,象power builder5.0以上版本提供的pipeline,Microsoft Access資料庫提供的資料匯入/匯出功能等。轉換方法參見有關資料說明。.

---- 2.3匹配字符集替換漢字

---- 對於1.3提到的情況,沒有很好的辦法,只能先把客戶端與伺服器端字符集匹配一致後,根據原輸入漢字的特徵碼替換漢字字元部分。

目前處理的一個問題, 客戶端是預設繁體字型。 但是登錄檔中的

HKEY_LOCAL_MACHINESOFTWAREORACLEHOME0 中的NLS_LANG 的值 SIMPLIFIED CHINESE_CHINA.ZHS16GBK 和客戶端OS的預設繁體字型不符合。 原則是OS的預設字型與Oracle的鍵值中的字符集應該匹配。

SIMPLIFIED CHINESE_CHINA.ZHS16GBK 簡體系統的nls_lang鍵值

TRADITIONAL CHINESE_TAIWAN.ZHT16MSWIN950 繁體系統的nls_lang鍵值

============================================

“在SQL*Plus中用insert插進的都是中文的,為什麼一存入伺服器後,再select出的就是???”

“有的時候,伺服器資料先匯出,重灌伺服器,再匯入資料,結果,發生資料查詢成???”

……

這些問題,一般是因為字符集設定不對造成的。

很久以來,字符集一直是困擾著眾多Oracle愛好者的問題,筆者從事Oracle資料庫管理和應用已經幾年了,經常接到客戶的類似上面提到的有關資料庫字符集的“告急”和“求救”,在此我們就這個問題做一些分析和探討。

首先,我們要明確什麼是字符集?字符集是一個位元組資料的解釋的符號集合,有大小之分,有相互的包括關係,如us7ascii就是zhs16gbk的子集,從us7ascii到zhs16gbk不會有資料解釋上的問題,不會有資料丟失,Oracle對這種問題也要求從子集到超集的匯出受支援,反之不行。在所有的字符集中utf8應該是最大,因為它基於unicode,雙位元組儲存字元(也因此在儲存空間上佔用更多)。

其次,一旦資料庫建立後,資料庫的字符集是不能改變的。因此,在設計和安裝之初考慮使用哪一種字符集是十分重要的。資料庫字符集應該是作業系統本地字符集的一個超集。存取資料庫的客戶使用的字符集將決定選擇哪一個超集,即資料庫字符集應該是所有客戶字符集的超集。

在實際應用中,和字符集問題關係最大的恐怕就是exp/imp了。在做exp/imp時,如果Client 和Server的nls_lang設定是一樣的,一般就沒有問題的。但是,要在兩個不同字符集的系統之間導資料就經常會有這樣或那樣的問題,如,匯出時資料庫的顯示正常,是中文,當匯入到其他系統時,就成了亂碼,這也是一類常見問題。

現在,介紹一些與字符集有關的NLS_LANG引數,

NLS_LANG格式:

NLS_LANG = language_territory.charset

有三個組成部分(語言、地域和字符集),每個成分控制了NLS子集的特性。其中:language 指定伺服器訊息的語言。

territory 指定伺服器的日期和數字格式。

charset 指定字符集

例如:

AMERICAN_AMERICA.US7SCII

AMERICAN _ AMERICA. ZHS16GBK



還有一些子集可以更明確定義NLS_LANG引數:

DICT.BASE 資料字典基本 表版本

DBTIMEZONE 資料庫時區

NLS_LANGUAGE 語言

NLS_TERRITORY 地域

NLS_CURRENCY 本地貨幣字元

NLS_ISO_CURRENCY ISO貨幣字元

NLS_NUMERIC_CHARACTERS 小數字符和組 分隔開

NLS_CHARACTERSET 字符集

NLS_CALENDAR 日曆系統

NLS_DATE_FORMAT 預設的日期格式

NLS_DATE_LANGUAGE 預設的日期語言

NLS_SORT 字元排序序列

NLS_TIME_FORMAT 時間格式

NLS_TIMESTAMP_FORMAT 時間戳格式

……

透過props$動態效能檢視,我們可以檢視資料庫的字符集資訊:

$> sqlplus internal

SQL> desc props$

Name Type Nullable Default Comments



NAME VARCHAR2(30)

VALUE$ VARCHAR2(4000) Y

COMMENT$ VARCHAR2(4000) Y



SQL> set arraysize 1

SQL> col value$ format a40

SQL> select name,value$ from props$ where name=‘NLS_CHARACTERSET’;

NAME VALUE$



NLS_CHARACTERSET ZHS16GBK

SQL> select * from sys.props$;



NAME VALUE$

DICT.BASE 2

DBTIMEZONE 0:00

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.6.0.0



NAME VALUE$

GLOBAL_DB_NAME SCPDB1

EXPORT_VIEWS_VERSION 8



22 rows selected



SQL>

從結果可以看出:

NLS_LANG = AMERICAN _ AMERICA. ZHS16GBK

雖然,資料庫的字符集是在create database的時候指定的,以後不允許改變,但在一個已經建立好的資料庫上,我們可以透過修改SYS.PROPS$來修改主要是對應客戶端的顯示,與儲存無關。

如:

SQL> conn / as sysdba

Connected.

SQL> SQL> select * from sys.props$

2 WHERE NAME=‘NLS_LANGUAGE’;



NAME VALUE$



NLS_LANGUAGE AMERICAN

SQL>

SQL> UPDATE sys.PROPS$ SET VALUE$=‘SIMPLIFIED CHINESE’

2 WHERE NAME=‘NLS_LANGUAGE’;

1 row updated

SQL>

SQL> select * from sys.props$

2 WHERE NAME=‘NLS_LANGUAGE’;

NAME VALUE$



NLS_LANGUAGE SIMPLIFIED CHINESE

SQL>

通常出現問題的原因,可分為三種:

1. 伺服器指定字符集與客戶字符集不同,而與載入資料字符集一致。

解決方法:對於這種情況,只需要設定客戶端字符集與伺服器端字符集一致就可以了,具體操作如下:

* 檢視當前字符集:

SQL> select * from sys.props$

2 WHERE NAME=‘NLS_CHARACTERSET’;

NAME VALUE$



NLS_CHARACTERSET ZHS16GBK

SQL>

可以看出,現在伺服器端Oracle資料庫的字符集為‘ZHS16GBK’

* 根據伺服器的字符集在客戶端作相應的配置或者安裝Oracle的客戶端軟體時指定:

如果還沒安裝客戶端,那麼在安裝客戶端時,指定與伺服器相吻合的字符集即可;如果已經安裝好了客戶端,並且客戶端為 sql*net 2.0 以下版本,進入Windows的系統目錄,編輯oracle.ini檔案,用US7ASCII替換原字符集,重新啟動計算機,設定生效;否則,如果,客戶端為 sql*net 2.0 以上版本,在Win98 下 運 行REGEDIT,第一步選HKEY_LOCAL_MACHINE,第二步選擇SOFTWARE, 第三步選擇 Oracle, 第四步選擇 NLS_LANG, 鍵 入 與服 務 器 端 相 同 的 字 符 集

(本例為:HKEY_LOCAL_MACHINE

SOFTWAREORACLENLS_LANG :AMERICAN _ AMERICA. ZHS16GBK)。

如果是UNIX客戶端,則:

SQL> conn / as sysdba

Connected.

SQL> SQL> UPDATE sys.PROPS$ SET VALUE$=‘SIMPLIFIED CHINESE’

2 WHERE NAME=‘NLS_LANGUAGE’;

1 row updated

SQL> COMMIT;

Commit complete

SQL>

2. 伺服器指定字符集與客戶字符集相同,與載入資料字符集不一致。

解決方法:強制載入資料字符集與伺服器端字符集一致。要做到這一點,可以透過重新建立資料庫,並選擇與原卸出資料一致的字符集,然後IMP資料,這種情況僅僅適用於空庫和具有同一種字符集的資料。

解決這類問題,也可以先將資料載入到具有相同字符集的伺服器上,然後用轉換工具卸出為foxbase 格式或access格式資料庫,再用轉換工具轉入到不同字符集的Oracle資料庫中,這樣就避免了Oracle字符集的困擾。目前資料庫格式轉換的工具很多,像power builder5.0以上版本提供的pipeline及Microsoft Access資料庫提供的資料匯入/匯出功能等。

3. 伺服器指定字符集與客戶字符集不同,與輸入資料字符集不一致。

對於這種情況,目前為止都還沒有太好的解決方法。

透過上面的瞭解,我們知道,導致在後期使用資料庫時出現種種關於字符集的問題,多半是由於在資料庫設計、安裝之初沒有很好地考慮到以後的需要,所以,我們完全可以透過在伺服器上和客戶端使用相同的字符集來避免由此類問題引出的麻煩。

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

相關文章