Oracle字符集討論的經(jīng)典版
提及Oracle字符集可以說是老生常,Oracle字符集問題的引起,主要是因?yàn)槠涞?ldquo;亂碼”問題。而亂碼的產(chǎn)生主要是因?yàn)榭蛻舳撕头?wù)器的實(shí)際應(yīng)用的字符集不同,其進(jìn)行字符集轉(zhuǎn)換而引起的。
不過很多提到了轉(zhuǎn)換,卻沒有提到這個(gè)轉(zhuǎn)換是在哪個(gè)階段和哪里發(fā)生的?是在服務(wù)器向塊里寫入數(shù)據(jù)的時(shí)候嗎?在客戶端還是在服務(wù)器端?
正確的答案是,普通字符串轉(zhuǎn)換發(fā)生在客戶端(具體來說是由OCI LIBRARY完成的),國(guó)家字符串經(jīng)過兩次轉(zhuǎn)換,***次發(fā)生在客戶端,第二次發(fā)生在服務(wù)器端。下面做個(gè)測(cè)試:
連接到:
- Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
- With the Partitioning, Real Application Clusters, OLAP and Data Mining options
- SQL> select * from nls_database_parameters where parameter like ‘%CHARACTERSET%’;
- PARAMETER VALUE
- ------------------------------ ------------------------------
- NLS_CHARACTERSET ZHS16GBK
- NLS_NCHAR_CHARACTERSET AL16UTF16
- SQL> create table t1(a varchar2(100));
表已創(chuàng)建。
- SQL>
- SQL> insert into t1 values (’中’);
已創(chuàng)建 1 行。
- SQL>
在本次連接中,我沒有設(shè)置NLS_LANG變量。則客戶端Oracle字符集為操作系統(tǒng)的缺省字符集ZHS16GBK。通過捕獲網(wǎng)絡(luò)包,可以發(fā)現(xiàn)客戶端傳送給客戶端的數(shù)據(jù)(不能上傳圖片,郁悶):
- 00000090 00 00 00 00 00 00 00 00 00 00 00 28 DB 00 01 1C ………..(….
- 000000A0 69 6E 73 65 72 74 20 69 6E 74 6F 20 74 31 20 76 insert.into.t1.v
- 000000B0 61 6C 75 65 73 20 28 27D6 D027 29 01 00 00 00 alues.(’..’)….
- 000000C0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
注意紅色的部分,16進(jìn)制D6 D0正是“中”字的GBK編碼。(關(guān)于怎么獲取漢字的各種編碼,暫且略過,如有需要再交流)
現(xiàn)在我們退出SQLPLUS,設(shè)置環(huán)境變量NLS_LANG:
- SQL> rollback;
回退已完成。
- SQL> exit
- Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
- With the Partitioning, Real Application Clusters, OLAP and Data Mining options
斷開
- C:\Documents and Settings\Administrator>set nls_lang=american_america.us7ascii
- C:\Documents and Settings\Administrator>sqlplus test/test@dmdb
- SQL*Plus: Release 10.2.0.1.0 - Production on Mon Jan 28 00:48:41 2008
- Copyright (c) 1982, 2005, Oracle. All rights reserved.
- Connected to:
- Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
- With the Partitioning, Real Application Clusters, OLAP and Data Mining options
- SQL> insert into t1 values (’中’);
- 1 row created.
抓獲的網(wǎng)絡(luò)包發(fā)現(xiàn),在SQL提交給服務(wù)器之前已經(jīng)轉(zhuǎn)換了。OCI庫(kù)認(rèn)為提交過來的編碼是US7ASCII,因此要將轉(zhuǎn)換為服務(wù)器端的ZHS16GBK編碼,然而“中”的編碼即16進(jìn)制D6 D0并不是有效的US7ASCII編碼,所以O(shè)RACLE OCI就轉(zhuǎn)為了轉(zhuǎn)省值3F3F(US7ASCII是單字節(jié)Oracle字符集,會(huì)認(rèn)為“中”字是兩個(gè)字符,因此為有兩個(gè)3F) 這就是“??”號(hào)的由來。
- 00000090 00 00 00 00 00 00 00 00 00 00 00 C8 1D FF 00 1C …………….
- 000000A0 69 6E 73 65 72 74 20 69 6E 74 6F 20 74 31 20 76 insert.into.t1.v
- 000000B0 61 6C 75 65 73 20 28 273F 3F27 29 01 00 00 00 alues.(’??’)….
- 000000C0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …………….
我們?cè)倏纯磳⒖蛻舳薔LS_LANG設(shè)置為simplified chinese_china.zhs16cgb231280會(huì)發(fā)生什么以上的相關(guān)內(nèi)容就是對(duì)再論Oracle字符集轉(zhuǎn)換的部分內(nèi)容的介紹。
【編輯推薦】
- Oracle SMON進(jìn)程的說明經(jīng)典版
- Oracle存儲(chǔ)過程的編寫經(jīng)驗(yàn)總結(jié)
- Oracle EXPLAIN PLAN實(shí)際應(yīng)用技巧心得
- Oracle數(shù)據(jù)庫(kù)設(shè)計(jì)規(guī)范化的前兩個(gè)要求
- Oracle樹的存儲(chǔ)過程的實(shí)際操作4步驟