再論字符集轉換(二)

magic007發表於2008-01-28

上一篇講到普通字串的轉換,本篇將講到國家字符集字串的轉換:

客戶端的NLS_LANG為預設值,即ZHS16GBK:

SQL> create table t1 ( id number ,aa varchar2(20),bb nvarchar2(20));

表已建立。

SQL> insert into t1 values (1,'中','中');

已建立 1 行。

捕獲的網路包如下:

00000090  00 00 00 00 00 00 EA 4E DB 00 AC 0D DC 00 00 00 .......N........
000000A0  00 00 23 69 6E 73 65 72 74 20 69 6E 74 6F 20 74 ..#insert.into.t
000000B0  31 20 76 61 6C 75 65 73 20 28 31 2C 27 D6 D0 27 1.values.(1,'..'
000000C0  2C 27 D6 D0 27 29 01 00 00 00 01 00 00 00 00 00 ,'..')..........

SQL> select dump(aa) aa,dump(bb) bb from t1;

AA                             BB
------------------------------ ------------------------------
Typ=1 Len=2: 214,208           Typ=1 Len=2: 78,45

客戶端傳送給資料庫的SQL語句,兩個“中”字均為D6 D0,但伺服器對NVARCHAR2類似的列作了轉換,將其從ZHS16GBK編碼轉換為AL16UTF16,轉換後的結果為10進位制78,45,即16進位制的4E  2D

因此對於國家字符集,客戶端在提交SQL時實際並不區分是否國家字符集,統一將SQL中的字元轉換為資料庫字符集,伺服器端再將國家字符集的列,從資料集字符集轉換為國家字符集。因此,我們可以設想,如果資料庫字符集與國家字符集不相容,會發生什麼?或者說是從資料庫字符集轉換為國家字符集是不是也會出現問題?我們用另一個資料庫測試一下:

SQL> select * from nls_database_parameters where parameter like '%CHARACTERSET%'
;

PARAMETER                      VALUE
------------------------------ ------------------------------
NLS_CHARACTERSET               US7ASCII
NLS_NCHAR_CHARACTERSET         AL16UTF16

將客戶端的NLS_LANG設定為AMERICAN_AMERICA.US7ASCII

SQL> create table t1 (id number,aa varchar2(20),bb nvarchar2(20));

SQL> insert into t1 values (1,'中','中');

1 row created.

SQL> select dump(aa) aa,dump(bb) bb from t1;

AA                             BB
------------------------------ ------------------------------
Typ=1 Len=2: 214,208           Typ=1 Len=4: 0,86,0,80

注意看這裡dump出的結果,與前一個庫dump出的結果,aa列是一樣的,而bb列dump出來變成了10進位制的0,86,0,80。我們看看這個值是怎麼來的:
1.客戶端NLS_LANG與資料庫字符集相同,因此在客戶端並沒對SQL中的字元進行轉換。
2.伺服器在執行SQL時,將bb列的值從資料庫字符集編碼(10進位制214,208)轉換為AL16UTF16編碼(這種編碼每個字元為固定的兩位元組)。由於資料庫字符集為單位元組字符集,在轉換時認為是兩個字元,同時US7ASCII字元的高位應該為0,而214-128=86,208-128=80.因此轉換後其結果就為字串“VP"了:

SQL> select * from t1;

        ID AA                   BB
---------- -------------------- --------------------
         1 中                   VP

因此,如果選擇了錯誤的資料庫字符集,雖然可以通過設定NLS_LANG將客戶端字符集設定為與伺服器字符集一致,但國家字符集卻有可能不能正常地從資料庫字符集轉換為國家字符集。

下篇要討論的是資料查詢時和資料匯出時的字符集轉換。

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

相關文章