Oracle資料庫字符集分析之一

物理狂人發表於2011-12-23
環境:

作業系統字符集
SIMPLIFIED CHINESE_CHINA.ZHS16GBK

test例項字符集:
SQL> select * from database_properties;
NLS_CHARACTERSET                                             WE8ISO8859P1

測試一:

1、建立測試表
SQL> create table test (text varchar2(50));

表已建立。

2、插入資料並檢視(客戶機NLS_LANG與伺服器NLG_LANG不一致)
SQL> insert into test values('上海大學');

已建立 1 行。

SQL>  select t.*, dump(text,1016) dump from test t;

TEXT       DUMP
---------- ----------------------------------------------------------

????   Typ=1 Len=4 CharacterSet=WE8ISO8859P1: bf,bf,bf,bf

分析:
1)沒有設定NLS_LANG時,客戶機採用系統字符集
因為沒有指定NLS_LANG在客戶機,所以採用的是系統的NLS_LANG,即 ZHS16GBK字符集。

2)當插入資料時,如果客戶機NLS_LANG與伺服器NLS_LANG不一致時,需要進行編碼轉化,因為轉換後的字符集不是轉換前字符集的超集,所以會出現不能表示轉換前字元的含義的情況
當將‘上海大學’插入資料庫時,資料庫發現客戶機的NLS_LANG與資料庫伺服器NLS_LANG不一致,於是將 ZHS16GBK表示的'上海大學'二進位制編碼轉換為WE8ISO8859P1對應的二進位制編碼,又因為WE8ISO8859P1無法有效表示‘上海大學,而將其轉換為????,其二進位制編碼為bf,bf,bf,bf,即將4個字元的‘上海大學’轉換為了4個位元組的'????'值,並存入資料庫。

3)當檢視資料時,如果客戶機NLS_LANG與伺服器NLS_LANG不一致時,需要進行編碼轉化,因為轉換後的字符集是轉換前字符集的超集,所以能正確表示轉換前字元的含義
當檢視時,同樣發現NLS_LANG不一致,於是將4位元組的WE8ISO8859P1值????轉換為 ZHS16GBK表示的4個字元????,即8個位元組

3、修改客戶機NLS_LANG,並再次查詢(客戶機NLS_LANG與伺服器NLG_LANG一致)
E:\Documents and Settings\Administrator>set NLS_LANG=.WE8ISO8859P1

SQL> select t.*, dump(text,1016) dump from test t;

TEXT       DUMP
---------- ------------------------------------------------------

靠靠       Typ=1 Len=4 CharacterSet=WE8ISO8859P1: bf,bf,bf,bf

分析:
因為將客戶機的NLS_LANG成與伺服器的NLS_LANG的字符集一致,所以當返回查詢結果時,不進行字符集的轉換,即將WE8ISO8859P1的????對應的二進位制bf,bf,bf,bf用系統字符集 ZHS16GBK的方式進行編碼讀取,即2個位元組表示一個字元,故是4個位元組,對應 ZHS16GBK的2個字元。

注意:
是讀取而不是轉換後讀取,如????4個位元組用ZHS16GBK讀取為‘靠靠’;????4個位元組轉換為ZHS16GBK後,變為8個位元組,4個字元的????,再讀取。

總結:
1)當在對一個資料庫伺服器進行操作時,請確保客戶機的NLS_LANG字符集與客戶機系統字符集一致,這樣可以在其與資料庫伺服器字符集不一致時,進行編碼轉換。

2)當在對一個資料庫伺服器進行寫入操作時,客戶機系統的字符集應最好為伺服器字符集的子集,或輸入資料庫的字元資料庫字符集包含的,這樣不會出現伺服器無法轉換的字元的情況。

3)當在對一個資料庫伺服器進行讀取操作時,客戶機系統的字符集應最好為伺服器字符集的超集,或資料庫輸出的字元資料被客戶機字符集所包含,這樣不會出現客戶機無法轉換的字元的情況。

參考文獻:

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

相關文章