一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

徹底搞懂Oracle字符集

 instl 2019-04-17
以下是對(duì)Oracle中的字符集進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以參考下

基本概念
字符集(Character set):
是一個(gè)系統(tǒng)支持的所有抽象字符的集合。字符是各種文字和符號(hào)的總稱,包括各國(guó)家文字、標(biāo)點(diǎn)符號(hào)、圖形符號(hào)、數(shù)字等。常見的字符集有ASCII,ZHS16GB231280,ZHS16GBK等。

字符編碼(Character Encoding):
是一套法則,使用該法則能夠?qū)ψ匀徽Z(yǔ)言的字符的一個(gè)集合(如字母表或音節(jié)表),與其它的一個(gè)集合(如電腦編碼)進(jìn)行配對(duì)。即在符號(hào)集合與數(shù)字系統(tǒng)之間建立對(duì)應(yīng)關(guān)系。與字符集相對(duì)應(yīng),常見的字符編碼有:ASCii,ZHS16GBK,ZHT16BIG5,ZHS32GB18030等。
字符集的定義其實(shí)就是字符的集合,而字符編碼則是指怎么將這些字符變成字節(jié)用于保存、讀取和傳輸。

萬(wàn)國(guó)碼(Unicode):包含了幾乎人類所有可用的字符,每年還在不斷的增加,可以看作是一種通用的字符集。它將全世界所有的字符統(tǒng)一化,統(tǒng)一編碼,不會(huì)再出現(xiàn)字符不兼容和字符轉(zhuǎn)換的問(wèn)題。
它有以下三種編碼方式:
1.UTF-32編碼:
固定使用4個(gè)字節(jié)來(lái)表示一個(gè)字符,存在空間利用效率的問(wèn)題。
2.UTF-16編碼:對(duì)相對(duì)常用的60000余個(gè)字符使用兩個(gè)字節(jié)進(jìn)行編碼,其余的使用4字節(jié)。
3.UTF- 8編碼:兼容ASCII編碼;拉丁文、希臘文等使用兩個(gè)字節(jié);包括漢字在內(nèi)的其它常用字符使用三個(gè)字節(jié);剩下的極少使用的字符使用四個(gè)字節(jié)。

Oracle字符集基本原理
在搞懂Oracle字符集基本原理之前,一定要先分清以下三個(gè)概念:
1. Oracle數(shù)據(jù)庫(kù)服務(wù)器字符集:即Oracle以哪種字符編碼存儲(chǔ)字符,可以通過(guò)以下語(yǔ)句查出數(shù)據(jù)庫(kù)字符集的設(shè)置。

復(fù)制代碼 代碼如下:

SQL> select * from v$nls_parameters where parameter='NLS_CHARACTERSET';
PARAMETER                      VALUE
------------------------------ -----------------
NLS_CHARACTERSET               AL32UTF8


2. 客戶端操作系統(tǒng)字符集:即客戶端操作系統(tǒng)以哪種字符編碼存儲(chǔ)字符。
如果是Windows,可以使用chcp命令獲得代碼頁(yè)(code page):

復(fù)制代碼 代碼如下:

C:Usersxianzhu>chcp
Active code page: 936


根據(jù)該代碼頁(yè),到微軟的官方文檔《National Language Support (NLS) API Reference》找到其對(duì)應(yīng)的字符集。 
如果是Linux,字符集在/etc/sysconfig/i18n設(shè)置:

復(fù)制代碼 代碼如下:

LANG="zh_CN.GB2312" (指定當(dāng)前操作系統(tǒng)的字符集) 
SUPPORTED="zh_CN.GB2312"(指定當(dāng)前操作系統(tǒng)支持的字符集) 
SYSFONT="lat0-sun16"(指定當(dāng)前操作系統(tǒng)的字體)


3. 客戶端NLS_LANG參數(shù):該參數(shù)用于向Oracle指示客戶端操作系統(tǒng)的字符集。
有了以上3個(gè)基本概念之后,我來(lái)闡述一下Oracle字符集轉(zhuǎn)換的基本原則:
1.設(shè)置客戶端的NLS_LANG為客戶端操作系統(tǒng)的字符集
2.如果數(shù)據(jù)庫(kù)字符集等于NLS_LANG,數(shù)據(jù)庫(kù)和客戶端傳輸字符時(shí)不作任何轉(zhuǎn)換
3.如果它們倆不等,則需要在不同字符集間轉(zhuǎn)換,只有客戶端操作系統(tǒng)字符集是數(shù)據(jù)庫(kù)字符集子集的基礎(chǔ)上才能正確轉(zhuǎn)換,否則會(huì)出現(xiàn)亂碼。
幾種常見情況分析
下面先看一個(gè)例子,再透過(guò)現(xiàn)象看本質(zhì),我們會(huì)針對(duì)這個(gè)例子進(jìn)行分析。
該例子如下:

復(fù)制代碼 代碼如下:

1. 數(shù)據(jù)庫(kù)字符集為Unicode(UTF-8編碼)
我們的數(shù)據(jù)庫(kù)版本是10.2.0.4.0,數(shù)據(jù)庫(kù)字符集是:
SQL> select * from v$nls_parameters where parameter='NLS_CHARACTERSET';
PARAMETER                                VALUE
---------------------------------------- ------------------------------
NLS_CHARACTERSET               AL32UTF8
2. 客戶端操作系統(tǒng)字符集為代碼頁(yè)936(字符集為ZHS16GBK)
可以使用chcp獲得windows的代碼頁(yè)(code page)
C:Documents and Settingsa105024Desktop>chcp
Active code page: 936
3. 創(chuàng)建測(cè)試表
SQL> create table test(id number,var varchar2(30));
Table created.
4. 插入數(shù)據(jù)
這里在同一個(gè)操作系統(tǒng)啟動(dòng)兩個(gè)session,session1的NLS_LANG設(shè)為和數(shù)據(jù)庫(kù)字符集一樣(即AL32UTF8):
C:Documents and Settingsa105024Desktop>set nls_lang=Simplified Chinese_China.AL32UTF8
連接數(shù)據(jù)庫(kù)并插入一條數(shù)據(jù):
Session_1>insert into test values(1,'中國(guó)');
1 row created.
Session_1>commit;
Commit complete.
session2的NLS_LANG設(shè)為和客戶端操作系統(tǒng)一樣(即ZHS16GBK):
C:Documents and Settingsa105024Desktop>set nls_lang=Simplified Chinese_China.ZHS16GBK
連接數(shù)據(jù)庫(kù)并插入一條數(shù)據(jù):
Session_2>insert into test values(2,'中國(guó)');
1 row created.
Session_2>commit;
Commit complete.
5. 執(zhí)行查詢
在session 1上執(zhí)行查詢:
Session_1>select * from test;
        ID VAR
---------- ---------------------
         1 中國(guó)
         2 涓   浗
在session 2上執(zhí)行查詢:
Session_2>select * from test;
        ID VAR
---------- --------------------
         1 ???
         2 中國(guó)


上面例子看起來(lái)很詭異,session1和2都能正常顯示自己插入的字符串,又都不能正常顯示對(duì)方插入的字符串。為了弄清楚,我們首先得知道數(shù)據(jù)庫(kù)里對(duì)這兩個(gè)字符串是怎么存儲(chǔ)的。我們可以使用dump函數(shù)獲得字符在數(shù)據(jù)庫(kù)的編碼:

復(fù)制代碼 代碼如下:

SQL> select id,dump(var,1016) from test;
ID DUMP(VAR,1016)
-- ------------------------------------------------------------
 1 Typ=1 Len=4 CharacterSet=AL32UTF8: d6,d0,b9,fa
 2 Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd


根據(jù)AL32UTF8的編碼,“中國(guó)”兩字的正確編碼為(都為3個(gè)字節(jié)):
中--e4,b8,ad
國(guó)--e5,9b,bd
因此session 1插入的字符串在數(shù)據(jù)庫(kù)中的編碼是錯(cuò)誤的,session 2正確。這也是為什么一定要設(shè)置NLS_LANG為客戶端操作系統(tǒng)的字符集。 
但是根據(jù)上面實(shí)驗(yàn)我們可以知道,數(shù)據(jù)庫(kù)中存儲(chǔ)正確,并不代表客戶端能正常顯示;同樣地,即時(shí)數(shù)據(jù)庫(kù)沒(méi)有正確存儲(chǔ),有時(shí)候客戶端也能夠正常顯示,這又是為什么呢?別急,請(qǐng)聽我慢慢道來(lái):

場(chǎng)景1:session 1插入,session 1查詢,在數(shù)據(jù)庫(kù)中存儲(chǔ)錯(cuò)誤,但顯示正確。
插入過(guò)程:
”中國(guó)“兩字在客戶端操作系統(tǒng)字符集ZHS16GBK中的編碼是”d6,d0,b9,fa",由于NLS_LANG和數(shù)據(jù)庫(kù)字符集相同,數(shù)據(jù)庫(kù)端對(duì)客戶端傳過(guò)來(lái)的字符編碼不進(jìn)行任何轉(zhuǎn)換直接存入數(shù)據(jù)庫(kù),因此數(shù)據(jù)庫(kù)中存儲(chǔ)的編碼也是“d6,d0,b9,fa”,
讀取過(guò)程:
數(shù)據(jù)庫(kù)端讀取的編碼是“d6,d0,b9,fa”,由于NLS_LANG和數(shù)據(jù)庫(kù)字符集相同,客戶端對(duì)數(shù)據(jù)庫(kù)端傳過(guò)來(lái)的字符編碼不進(jìn)行任何轉(zhuǎn)換直接顯示,編碼”d6,d0,b9,fa“在客戶端操作系統(tǒng)字符集ZHS16GBK對(duì)應(yīng)的漢字為“中國(guó)”。

從以上分析可知,雖然讀取時(shí)正確的,但那是因?yàn)樨?fù)負(fù)得正,實(shí)際上數(shù)據(jù)庫(kù)中存儲(chǔ)是錯(cuò)誤的,因此要特別小心這種情況,在生成庫(kù)中要避免。其實(shí)只要對(duì)它進(jìn)行l(wèi)ength操作就能輕易揭開它的假面具:

復(fù)制代碼 代碼如下:

Session_1>select length(var) from test where id=1;
LENGTH(VAR)
-----------
          3


得出的長(zhǎng)度居然為3!實(shí)際的長(zhǎng)度只是2,這會(huì)帶來(lái)很多麻煩。

場(chǎng)景2:session 1插入,session 2查詢,在數(shù)據(jù)庫(kù)中存儲(chǔ)錯(cuò)誤,顯示也錯(cuò)誤。
插入過(guò)程和場(chǎng)景1一樣,這里就不再累述。
讀取過(guò)程:
數(shù) 據(jù)庫(kù)端讀取的編碼是“d6,d0,b9,fa”,由于NLS_LANG和數(shù)據(jù)庫(kù)字符集不同,客戶端對(duì)數(shù)據(jù)庫(kù)端傳過(guò)來(lái)的字符編碼進(jìn)行轉(zhuǎn)換,數(shù)據(jù)庫(kù)端字符集 AL32UTF8里編為“d6,d0,b9,fa”無(wú)法在客戶端操作系統(tǒng)字符集ZHS16GBK里找到對(duì)應(yīng)的編碼,所以只好用?代替。

場(chǎng)景3:session 2插入,session 1查詢,在數(shù)據(jù)庫(kù)中存儲(chǔ)正確,但顯示錯(cuò)誤。
插入過(guò)程:
” 中國(guó)“兩字在客戶端操作系統(tǒng)字符集ZHS16GBK中的編碼是”d6,d0,b9,fa",由于NLS_LANG和數(shù)據(jù)庫(kù)字符集不同,Oracle會(huì)進(jìn)行 字符編碼轉(zhuǎn)換,也就是將字符集ZHS16GBK里“中國(guó)”的編碼“d6,d0,b9,fa"轉(zhuǎn)換為字符集"AL32UTF8"里”中國(guó)“的編 碼”e4,b8,ad,e5,9b,bd“。
讀取過(guò)程:
數(shù)據(jù)庫(kù)端讀取的編碼 是”e4,b8,ad,e5,9b,bd“,由于NLS_LANG和數(shù)據(jù)庫(kù)字符集相同,客戶端對(duì)數(shù)據(jù)庫(kù)端傳過(guò)來(lái)的字符編碼不進(jìn)行任何轉(zhuǎn)換直接顯示,編 碼”e4,b8,ad,e5,9b,bd“在客戶端操作系統(tǒng)字符集ZHS16GBK對(duì)應(yīng)的漢字為“涓   浗”(原本2個(gè)字符,現(xiàn)在變成了3個(gè)字符,因?yàn)閆HS16GBK的漢字以2個(gè)字節(jié)編碼)。

場(chǎng)景4:session 2插入,session 2查詢,在數(shù)據(jù)庫(kù)中存儲(chǔ)正確,顯示也正確。
插入過(guò)程和場(chǎng)景3類似。
讀取過(guò)程:
數(shù) 據(jù)庫(kù)端讀取的編碼是”e4,b8,ad,e5,9b,bd“,由于NLS_LANG和數(shù)據(jù)庫(kù)字符集不同,客戶端對(duì)數(shù)據(jù)庫(kù)端傳過(guò)來(lái)的字符編碼進(jìn)行轉(zhuǎn)換,數(shù)據(jù) 庫(kù)端字符集AL32UTF8里”中國(guó)“兩字的編碼”e4,b8,ad,e5,9b,bd“轉(zhuǎn)換成客戶端操作系統(tǒng)字符集ZHS16GBK里“中國(guó)”兩字的編 碼“d6,d0,b9,fa",并正常顯示。
這種情況雖然經(jīng)過(guò)了兩次轉(zhuǎn)換,都確實(shí)最正確、最推薦的方式。

附錄:Oracle 字符集超集和子集的對(duì)應(yīng)關(guān)系可查看:http://download.oracle.com/docs/cd/B19306_01/server.102/b14225/applocaledata.htm#sthref1988

結(jié)論:
NLS_LANG只和客戶端操作系統(tǒng)的字符集相關(guān),如果客戶端操作系統(tǒng)的字符集和數(shù)據(jù)庫(kù)字符集間無(wú)法正確轉(zhuǎn)換,則應(yīng)該首先改變客戶端終端的字符集,而不是簡(jiǎn)單地把NLS_LANG設(shè)為和數(shù)據(jù)庫(kù)字符集一樣。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    午夜精品一区免费视频| 香蕉网尹人综合在线观看| 五月激情婷婷丁香六月网| 久久99夜色精品噜噜亚洲av| 国产亚洲系列91精品| 日韩中文高清在线专区| 国产一区二区三区不卡| 亚洲中文字幕剧情在线播放| 日韩欧美国产精品自拍| 国产女优视频一区二区| 欧美小黄片在线一级观看| 日本加勒比在线观看不卡| 午夜精品成年人免费视频| 国产免费一区二区三区av大片 | 精品国产丝袜一区二区| 日本高清视频在线播放| 日韩欧美好看的剧情片免费| 国产在线一区二区三区不卡| 久久精品中文扫妇内射| 欧美一本在线免费观看| 国产又色又粗又黄又爽| 欧美精品久久一二三区| 99在线视频精品免费播放| 国产一级内片内射免费看| 亚洲国产精品国自产拍社区| 日本不卡一区视频欧美| 日本少妇aa特黄大片| 久久re6热在线视频| 日韩精品综合免费视频| 99久久成人精品国产免费| 免费大片黄在线观看国语| 日本午夜福利视频免费观看| 99精品人妻少妇一区二区人人妻| 麻豆一区二区三区精品视频| 欧美日韩无卡一区二区| 国产91人妻精品一区二区三区 | 亚洲一区二区三区有码| 黄色污污在线免费观看| 亚洲做性视频在线播放| 日韩精品日韩激情日韩综合| 久久综合亚洲精品蜜桃|