黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

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

系統(tǒng) 2468 0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

測試環(huán)境:

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

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

數(shù)據(jù)庫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('測試');

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),查詢出來的是混亂的字符,我們把這些字符轉(zhuǎn)換為2進(jìn)制就是
110010   1100010   1001010   1010100
補(bǔ)全8位就是       00110010  01100010  01001010  01010100
我們把首位換成1   10110010  11100010  11001010  11010100
                
                

我們來看正確的存儲:
                
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('測試');

1 row created.

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

NAME DUMP(NAME)
---------- ------------------------------
測試 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è)測試說明在US7ASCII轉(zhuǎn)換中文的時(shí)候除去了首位的 1,這樣就丟失了元數(shù)據(jù),導(dǎo)致亂碼出現(xiàn),NLS_LANG的轉(zhuǎn)換作用由此可加一斑!

              

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

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

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

我們來看一個(gè)簡單的測試

測試環(huán)境:

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

客戶端NLS_LANG為US7ASCII

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

我們知道這個(gè)時(shí)候,存入的數(shù)據(jù),數(shù)據(jù)庫不進(jìn)行任何轉(zhuǎn)換,在以下的測試中,我們看到中文在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('測試');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from test;

NAME
----------
測試

1 row selected.

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

NAME       DUMP(NAME)
---------- ------------------------------
測試       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é)語:

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

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

-----

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


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論