日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

字符集問(wèn)題的初步探討(六)-亂碼的產(chǎn)生

系統(tǒng) 2107 0

最后我們來(lái)討論一下亂碼的產(chǎn)生。

通常在我們的現(xiàn)實(shí)環(huán)境中,存在3個(gè)字符集設(shè)置。

第一: 客戶端應(yīng)用字符集(Client Application Character Set)

第二: 客戶端NLS_LANG參數(shù)設(shè)置

第三: 服務(wù)器端,數(shù)據(jù)庫(kù)字符集(Character Set)設(shè)置

我們說(shuō),一個(gè)字符在客戶端應(yīng)用(比如SQLPLUS,CMD,NOTEPAD等)中以怎樣的字符顯示取決于客戶端操作系統(tǒng),客戶端能夠顯示怎樣的字符,
我們就可以在應(yīng)用中錄入這些字符,至于這些字符能否在數(shù)據(jù)庫(kù)中正常存儲(chǔ),就和另外的兩個(gè)字符集設(shè)置緊密相關(guān)了。

在傳輸過(guò)程中,客戶端NLS_LANG主要用于進(jìn)行轉(zhuǎn)換判斷

如果NLS_LANG等于數(shù)據(jù)庫(kù)字符集,則不進(jìn)行任何轉(zhuǎn)換直接把字符插入數(shù)據(jù)庫(kù)

如果不同則進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換主要有兩個(gè)任務(wù)

  • 如果存在對(duì)應(yīng)關(guān)系,則把相應(yīng)二進(jìn)制編碼經(jīng)過(guò)映射后(這一步映射以后,所代表的字符可能發(fā)生轉(zhuǎn)換)傳遞給數(shù)據(jù)庫(kù)
  • 如果不存在對(duì)應(yīng)關(guān)系,則傳遞一個(gè)替換字符(很多平臺(tái)就是?)

數(shù)據(jù)庫(kù)字符集,在和客戶端NLS_LANG不同時(shí),會(huì)把經(jīng)過(guò)NLS_LANG轉(zhuǎn)換的字符進(jìn)行進(jìn)一步處理

  • 對(duì)于?(即不存在對(duì)應(yīng)關(guān)系的字符)直接以?形式存放入數(shù)據(jù)庫(kù)
  • 對(duì)于其他字符,在NLS_LANG和數(shù)據(jù)庫(kù)字符集之間進(jìn)行轉(zhuǎn)換后存入。

以下我們來(lái)看一下最為常見(jiàn)的字符集及亂碼的產(chǎn)生:

1.當(dāng)NLS_LANG字符集與數(shù)據(jù)庫(kù)字符集不同,同時(shí)NLS_LANG不同于Server端字符集設(shè)置

在這種情況下,存在兩種可能:

  • 客戶端輸入的字符在NLS_LANG中沒(méi)有對(duì)應(yīng)的字符,這時(shí)無(wú)法轉(zhuǎn)換,NLS_LANG使用替換字符替代這些無(wú)法映射的字符(這一步轉(zhuǎn)換在TTS中
    完成),在很多字符集中這個(gè)替代字符就是”?”
  • 當(dāng)客戶端的字符在NLS_LANG中對(duì)應(yīng)了不同的字符時(shí),傳遞給數(shù)據(jù)庫(kù)以后發(fā)生轉(zhuǎn)換,存儲(chǔ)的是字符,但是已經(jīng)丟失了元數(shù)據(jù),數(shù)據(jù)庫(kù)中
    的字符不再代表客戶端的輸入。而且這個(gè)過(guò)程不可逆,這也就是為什么很多時(shí)候在客戶端輸入的是正常的編碼,查詢之后會(huì)得到未知字符的原因。

字符集問(wèn)題的初步探討(六)-亂碼的產(chǎn)生

我們通過(guò)上圖來(lái)簡(jiǎn)單說(shuō)明一下這個(gè)過(guò)程,當(dāng)客戶端在WE8ISO8859P15字符集時(shí),輸入歐元符號(hào): €,這時(shí)客戶端NLS_LANG和數(shù)據(jù)庫(kù)端字符集不同,
進(jìn)行第一次轉(zhuǎn)換,客戶端€符號(hào)編碼是A4,在NLS_LANG轉(zhuǎn)換時(shí),A4對(duì)應(yīng)了NLS_LANG中的‘¤’,這一步的轉(zhuǎn)換產(chǎn)生了錯(cuò)誤映射。由于數(shù)據(jù)庫(kù)字符集不
同于NLS_LANG設(shè)置,這時(shí)進(jìn)一步的轉(zhuǎn)換發(fā)生了,存入數(shù)據(jù)庫(kù)的編碼變成了C2A4,雖然同NLS_LANG進(jìn)行了正確的轉(zhuǎn)換,但是客戶端錄入的數(shù)據(jù)已經(jīng)
損壞或者丟失了。

我們可以用我們熟悉的字符集做一個(gè)簡(jiǎn)單的測(cè)試:

測(cè)試環(huán)境:

客戶端應(yīng)用為中文18030字符集

NLS_LANG設(shè)置為US7ASCII字符集

數(shù)據(jù)庫(kù)CHARACTER SET為ZHS16GBK

                c:\>set NLS_LANG=AMERICAN_AMERICA.US7ASCII

c:\>sqlplus eygle/eygle

SQL*Plus: Release 9.2.0.4.0 - Production on Tue Nov 4 01:19:57 2003

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production

SQL> insert into test values('測(cè)試');

1 row created.

SQL> select name,dump(name) from test;

NAME DUMP(NAME)
--------------------------------------------------
2bJT Typ=1 Len=4:
                
                   50,98,74,84
                
                
                  這時(shí)候我們發(fā)現(xiàn),查詢出來(lái)的是混亂的字符,我們把這些字符轉(zhuǎn)換為2進(jìn)制就是
110010   1100010   1001010   1010100
補(bǔ)全8位就是       00110010  01100010  01001010  01010100
我們把首位換成1   10110010  11100010  11001010  11010100
                
                

我們來(lái)看正確的存儲(chǔ):
                
c:\>set nls_lang=AMERICAN_AMERICA.ZHS16GBK

c:\>sqlplus eygle/eygle

SQL*Plus: Release 9.2.0.4.0 - Production on Tue Nov 4 01:40:18 2003

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production

SQL> insert into test values('測(cè)試');

1 row created.

SQL> col dump(name) for a30
SQL> select name,dump(name) from test;

NAME DUMP(NAME)
---------- ------------------------------
測(cè)試 Typ=1 Len=4: 178,226,202,212

1 row selected.

                我們把這個(gè)結(jié)果轉(zhuǎn)換為2進(jìn)制表示
                
10110010 11100010 11001010 11010100

這個(gè)結(jié)果正是我們前面亂碼首位補(bǔ)全1后的結(jié)果。

這個(gè)測(cè)試說(shuō)明在US7ASCII轉(zhuǎn)換中文的時(shí)候除去了首位的 1,這樣就丟失了元數(shù)據(jù),導(dǎo)致亂碼出現(xiàn),NLS_LANG的轉(zhuǎn)換作用由此可加一斑!

              

3. NLS_LANG和數(shù)據(jù)庫(kù)字符集相同時(shí)
在這種情況下,數(shù)據(jù)庫(kù)端對(duì)客戶端傳遞過(guò)來(lái)的編碼不進(jìn)行任何轉(zhuǎn)換(這樣可以提高性能),直接存儲(chǔ)進(jìn)入數(shù)據(jù)庫(kù),那么這時(shí)候就存在和上面同樣的問(wèn)題,
如果客戶端傳遞過(guò)來(lái)的字符集在數(shù)據(jù)庫(kù)中有正確的對(duì)應(yīng)就可以正確存儲(chǔ),如果沒(méi)有,就會(huì)被替換字符置換成?,亂碼就這樣產(chǎn)生了。

字符集問(wèn)題的初步探討(六)-亂碼的產(chǎn)生

如上圖所示,當(dāng)NLS_LANG和數(shù)據(jù)庫(kù)字符集設(shè)置相同都為UTF8時(shí),客戶端的歐元符號(hào)的編碼A4就不會(huì)經(jīng)過(guò)任何轉(zhuǎn)換就插入到數(shù)據(jù)庫(kù)中,而在UTF8的數(shù)
據(jù)庫(kù)中,A4代表的是一個(gè)非法字符。

我們來(lái)看一個(gè)簡(jiǎn)單的測(cè)試

測(cè)試環(huán)境:

客戶端字符集應(yīng)用為中文GB18030

客戶端NLS_LANG為US7ASCII

數(shù)據(jù)庫(kù)字符集為US7ASCII

我們知道這個(gè)時(shí)候,存入的數(shù)據(jù),數(shù)據(jù)庫(kù)不進(jìn)行任何轉(zhuǎn)換,在以下的測(cè)試中,我們看到中文在US7ASCII字符集下得以正確顯示。

              c:\>set nls_lang=AMERICAN_AMERICA.US7ASCII

c:\>sqlplus eygle/eygle

SQL*Plus: Release 9.2.0.4.0 - Production on Tue Nov 4 01:02:04 2003

Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, Oracle Label Security, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production

SQL> insert into test values('測(cè)試');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from test;

NAME
----------
測(cè)試

1 row selected.

SQL> col dump(name) for a30
SQL> select name,dump(name) from test;

NAME       DUMP(NAME)
---------- ------------------------------
測(cè)試       Typ=1 Len=4: 178,226,202,212

1 row selected.

SQL> select * from nls_database_parameters;

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_LANGUAGE                   AMERICAN
NLS_TERRITORY                  AMERICA
NLS_CURRENCY                   $
NLS_ISO_CURRENCY               AMERICA
NLS_NUMERIC_CHARACTERS         .,
NLS_CHARACTERSET               US7ASCII
NLS_CALENDAR                   GREGORIAN
NLS_DATE_FORMAT                DD-MON-RR
NLS_DATE_LANGUAGE              AMERICAN
NLS_SORT                       BINARY
NLS_TIME_FORMAT                HH.MI.SSXFF AM

PARAMETER                      VALUE
------------------------------ ----------------------------------------
NLS_TIMESTAMP_FORMAT           DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT             HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT        DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY              $
NLS_COMP                       BINARY
NLS_LENGTH_SEMANTICS           BYTE
NLS_NCHAR_CONV_EXCP            FALSE
NLS_NCHAR_CHARACTERSET         AL16UTF16
NLS_RDBMS_VERSION              9.2.0.4.0

20 rows selected.

SQL>
       
            

結(jié)語(yǔ):

對(duì)于DBA來(lái)說(shuō),有一個(gè)很重要的原則就是:不要把你的數(shù)據(jù)庫(kù)置于危險(xiǎn)的境地!

這就要求我們,在進(jìn)行任何可能對(duì)數(shù)據(jù)庫(kù)結(jié)構(gòu)發(fā)生改變的操作之前,先做有效的備份,很多DBA沒(méi)有備份的操作中得到了慘痛的教訓(xùn)。

-----

字符集問(wèn)題的初步探討(六)-亂碼的產(chǎn)生


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 张掖市| 微山县| 肃北| 京山县| 合阳县| 什邡市| 嘉义县| 盘锦市| 东阳市| 长葛市| 鄂州市| 蒲江县| 洛阳市| 香港| 长顺县| 凤山县| 宕昌县| 英山县| 汉源县| 红原县| 木里| 社旗县| 黎城县| 隆昌县| 文成县| 尼木县| 丰县| 清新县| 敦化市| 临潭县| 和政县| 承德县| 阳江市| 石嘴山市| 莱州市| 宜春市| 苍山县| 黎川县| 齐齐哈尔市| 龙陵县| 永丰县|