一、字符集的概念
1、字符編碼(character encoding):
字符編碼是一種法則,在數字與符號之間建立的對應關系。不同的國家有不同的語言,包含的文字、標點符號、圖形符號各有不同。例如在ASCII編碼中,用數字97表達字符'a'與字符集相對應,常見的字符編碼有ASCII,GBK,GB18030,Unicode等。
2、字符集(Character set)
字符集是字符的集合,字符是文字和符號的總稱,用ASCII編碼的字符集稱之為ASCII字符集,用GBK編碼的字符集稱之為GBK字符集。
3、國際編碼(Unicode)
為了解決傳統的字符編碼方案的局限,1994年發布了Unicode(國際編碼、統一碼、萬國碼、單一碼、通用碼),它是計算機科學領域里的一項業界標准,包括字符集、編碼方案等。Unicode 將全世界所有的字符統一化,統一編碼,再也不存在字符集不兼容和字符轉換的問題。
Unicode 有以下三種編碼方式:
1)UTF-8:兼容ASCII編碼;拉丁文、希臘文等使用兩個字節;包括漢字在內的其它常用字符使用三個字節;剩下的極少使用的字符使用四個字節。
2)UTF-16:對相對常用的60000余個字符使用兩個字節進行編碼,其余的使用4字節。
3)UTF-32:固定使用4個字節來表示一個字符,存在空間利用效率的問題。
4、漢字的編碼
支持漢字(簡體中文)的編碼有GB2312、GB13000、GBK、GB18030和Unicode(UTF-8、UTF-16、UTF-32)。
1)GB2312
僅包含大部分的常用簡體漢字,但已經不能適應現在的需要。
2)GB13000
由於GB2312的局限性,國家標准化委員會制定了GB13000編碼;但由於當時的硬件和軟件都已經支持了GB2312,而GB13000與GB2312完全不兼容,所以沒有能夠得到大范圍的推廣使用。
3)GBK
有了GB13000的教訓,中國國家標准化委員會制定了GBK標准,並兼容了GB2312標准,同時在GB2312標准的基礎上擴展了GB13000包含的字;由於該標准有微軟的支持,得到了廣泛的應用。
4)GB18030
GB18030編碼比GBK又新增了幾千個漢字,但由於碼位不足使用了2byte與4byte混合編碼方式,這給軟件開發增加了難度。
5)Unicode
包含全世界所有國家需要用到的字符,是國際編碼,通用性強。
5、漢字的編碼選擇
在操作系統和數據庫中,常用的漢字編碼有GBK、GB18030和Unicode,GBK和GB18030的優勢是占用空間小,Unicode的優勢是全球化的支持。
在應用開發中,如果不考慮全球化,最好的選擇是GBK和GB18030。
6、編碼的轉換
GBK和GB18030與Unicode編碼之間需要轉換,否則會出現漢字亂碼。
二、Oracle的字符集
1、字符集和國家字符集
字符集在創建數據庫實例時指定,可以指定字符集(CHARACTER SET)和國家字符集(NATIONAL CHARACTER SET)。
1)字符集(CHARACTER SET)
用來存儲char、varchar2、clob、long等類型數據,還可以用來標識表名、列名以及PL/SQL變量等。
2)國家字符集(NATIONAL CHARACTER SET)
用以存儲nchar、nvarchar2、nclob等類型數據。國家字符集實質上是為Oracle選擇的附加字符集,主要作用是為了增強字符處理能力,因為nchar數據類型可以提供對亞洲使用定長多字節編碼的支持,而數據庫字符集則不一定能。國家字符集只能在unicode編碼中的AF16UTF16和UTF8中選擇,默認值是AF16UTF16。
2、支持中文的字符集
Oracle支持漢字(簡體中文,繁體不介紹)的字符集有多種,常用的有ZHS16GBK、UTF8、AL32UTF8和AL16UTF16。
1)ZHS16GBK
表示簡體中文,一個字符需要16位比特,采用GBK編碼標准。
2)UTF8
Oracle從8i版本開始使用的屬於UTF-8編碼的字符集,采用的Unicode標准為3.0,在11.2版本中,UTF8已經不是推薦字符集列表中的一員了。
3)AL32UTF8
與UTF8相比,它采用的Unicode版本更新,在10g版本中使用的是Unicode 4.01標准,而UTF8因為兼容性的考慮,在10g版本中用的是Unicode 3.0標准。
4)AL16UTF16
是ORACLE第一種采用UTF-16編碼方式的字符集,從ORACLE9開始使用,是作為缺省的國家字符集使用,它不能被用作數據庫的字符集。
3、NLS_LANG參數
Oracle數據庫字符集最重要的參數是NLS_LANG參數。
格式: NLS_LANG='language_territory.charset',不區分大小寫,例如' SIMPLIFIED CHINESE_CHINA.ZHS16GBK'。
它有三個組成部分:語言(language)、地域(territory)和字符集(charset)。
其中:
language:數據庫服務器提示信息的語言。
territory:數據庫的日期和數字格式,意義不大。
charset:數據庫的字符集。
真正影響數據庫字符集的其實是第三部分charset,兩個數據庫之間的字符集只要第三部分相同,交換數據時中文不會出現亂碼。language影響的只是提示信息是中文還是英文。
三、服務端的字符集
1、查看服務端字符集
執行以下SQL可以查看服務端的字符集。
select * from NLS_DATABASE_PARAMETERS where parameter like '%CHARACTERSET%';

執行以下SQL也可以查看服務端的字符集。
select userenv('language') from dual;

2、修改服務端字符集
Oracle數據庫實例創建后,如果沒有開始業務運行,可以修改字符集,如果已經業務化運行,不建議修改字符集,會造成數據中的漢字亂碼。
用DBA權限,執行以下步驟修改Oracle數據庫的字符集(例如修改為ZHS16GBK)。
1)修改服務端操作系統的NLS_LANG環境變量。
export NLS_LANG='Simplified Chinese_China.ZHS16GBK'
2)關閉Oracle數據庫。
shutdown immediate;
3)把數據庫啟動到mount狀態。
startup mount;
4)把數據庫改為restricted模式。
alter system enable restricted session;
alter system set job_queue_processes=0;
alter system set aq_tm_processes=0;
5)打開數據庫。
alter database open;
6)修改數據庫的字符集。
alter database character set internal_use ZHS16GBK;
7)重啟數據庫。
shutdown immediate;
startup;
四、客戶端的字符集
Oracle客戶端的字符集必須與服務端相同,否則中文會出現亂碼。
1、Linux環境
客戶端的字符集由NLS_LANG環境變量控制。
1)查看NLS_LANG環境變量。
env|grep NLS_LANG

2)設置環境變量
修改環境變量參數文件(系統或用戶的profile文件)。
export NLS_LANG='Simplified Chinese_China.ZHS16GBK'
2、Windows環境
打開注冊表( 執行regedit.exe)
HKEY_LOCAL_MACHINE -> SOFTWARE -> ORACLE -> KEY_OraClient11g_home1

五、應用經驗
1)數據庫在業務化之前,就應該確定Oracle的字符集,然后不再改變。數據庫在業務化后,修改字符集是一件很麻煩的事情,最好別惹這個麻煩。
2)如果項目沒有全球化的需求,數據庫字符集建議采用ZHS16GBK,操作系統語言建議采用gbk。
3)只要把客戶端和服務端設置成相同的字符集,就不會有亂碼,沒什么技術難點。
4)雖然GB18030字符集比GBK更豐富,但是GB18030中有部分漢字是4字節,這一點讓程序員很郁悶,所以,程序員更傾向GBK字符集。
六、版權聲明
C語言技術網原創文章,轉載請說明文章的來源、作者和原文的鏈接。
來源:C語言技術網(www.freecplus.net)
作者:碼農有道
如果文章有錯別字,或者內容有錯誤,或其他的建議和意見,請您留言指正,非常感謝!!!
