使用常用的gbk,utf8以及ascii說明(oracle中對應hs16gbk,al32utf8,us7ascii)。
其中,ascii為經典的單位元組編碼,採用7位,只能表示128個常用字元以及計算機控制字元,不能顯示中文等字元;gbk為中國大陸標準,16位,簡體中文字符集標準;utf8為unicode的一種最常用實現,相容ascii的字元使用1位,其餘字元都採用3位,可以表示任何字元。utf8其實已經可以稱為國際標準字符集編碼,應首先考慮使用utf8。需要說明的是,雖然gbk跟utf8都能表示中文字元,但每個字元的編碼是不一樣的,所以不能認為是相容的。
其實,oracle的字元系統很簡單,主要由3部分組成:
[b]客戶終端字符集[/b],[b]nls_lang環境變數字符集[/b],[b]資料庫使用的字符集[/b]。其中,客戶終端各種各樣,比如windows下cmd,unix/linux下terminal/console,甚至如toad等工具也可以視為乙個終端。我們使用windows cmd舉例說明,cmd使用了gbk編碼(好像不能修改)
nls_lang環境變數決定了終端與伺服器連線時,要不要轉換字符集,如果nls_lang和伺服器端資料庫使用的編碼不一樣,那就要進行轉碼;如果設為一樣,就不會發生轉碼。
比如乙個終端cmd查詢一張資料庫表,而其nls_lang設為american_america.zhs16gbk,而資料庫為american_america.al32utf8,則資料庫中的資料傳到終端時,首先要進行utf8到gbk的轉碼。
而轉碼又有兩種情況,a.就是乙個字元在兩中編碼裡都有,就是具體的碼文不一樣;b.轉碼時發現乙個字元在另一種編碼裡沒有,則直接用替代字元代替,而這一般就是『?』字元了。這裡要注意的是,我們一般所說的亂碼有2種,一種就是b所說的『?』,而另一種出現的奇奇怪怪的字元就是由於nls_lang設定等轉碼原因造成的。
而資料庫使用的字符集就是資料庫實際使用的字符集。
現舉例說明:
先建立oracle資料庫utf8使用al32utf8編碼,使用cmd(gbk),分以下幾種情況:
a. 設nls_lang也為zhs16gbk,則insert中文時,伺服器發現客戶端nls_lang為gbk,則要轉換對映。輸入「我靠」;因為終端為cmd,所以輸入的字符集都是gbk編碼的,假設「我靠」的gbk編碼為0xaabb,則0xaabb要對映為utf8(假設「我靠」的utf8編碼為0xccddee)編碼,存入資料庫,則資料中儲存了utf8編碼的「我靠「。然後,再使用cmd進行select查詢,資料庫發現nls_lang為zhs16gbk,則把」我靠「從utf8碼0xccddee轉為gbk的0xaabb,然後正常在cmd中顯示」我靠「兩字。
b. 設nls_lang也為al32utf8,則從cmd輸入「我靠「時,伺服器發現客服端nls_lang為utf8,則它不進行轉換,直接存0xaabb進資料庫;當select時,因為也不要轉換,所以直接發0xaabb給終端,而0xaabb在終端cmd(gbk)裡顯示為「我靠」,也能正常顯示。但要注意的是,這時對伺服器來說,存在資料庫裡的內容其實是不正確的,不是正確的「我靠」的utf8編碼;而只是存了個「我靠「的gbk編碼。
c. 先設nls_lang為utf8,輸入完「我靠「後,改nls_lang為gbk,再做select,發現顯示為亂碼了。這種就是前面說的因為轉碼問題造成的亂碼。因為資料庫一開始存的是」我靠「的gbk碼0xaabb;然後做select時,因為使用了改為gbk的nls_lang,則資料庫要進行轉碼了,就是要把utf8中的0xaabb轉為gbk碼,假設utf8中0xaabb表示的是」b??「,那就是要把」b??「轉為gbk碼,然後在cmd中用gbk顯示了」b??「亂碼。
然後,我們再次建立乙個us7ascii碼的資料庫chr。
d. 設nls_lang為american_america.us7ascii,輸入「我靠「,然後再select,發現竟然能正常顯示中文。這是因為由於資料庫編碼和nls_lang編碼一樣,所以不進行轉碼,直接把」我靠「的gbk碼0xaabb輸入了資料庫。而select時,由於也不要轉碼,所以又直接把0xaabb傳了回來,在cmd(gbk)中就顯示了」我靠「。
e. 延續d的情況,再設nls_lang為american_america.zhs16gbk,再做select,發現返回nr??,這種情況還是前面所說的轉碼造成的亂碼,因為gbk是相容ascii的,只是這裡還是進行了錯誤的轉碼,因為ascii中的0xaabb轉碼成gbk顯示,就是nr??。
f. 設nls_lang為american_america.zhs16gbk,輸入「我靠「,然後再select,發現返回兩個??;這是因為」我靠「的gbk編碼要轉碼到uscii時,因為uscii裡沒有」我靠「兩個字元的編碼,所以不相容,直接用兩個?代替;而select時,因為ascii裡的?和gbk裡的?是相容的,所以轉碼後,cmd裡也顯示兩個?。
綜上所述,可以得出如下規範:
1. 資料庫字元應該至少使用gbk,最好是utf8字符集,這樣至少基本上不會出現全問號亂碼的情況,因為不會出現找不到對應字元,而採用?等字元代替的情況。情況f其實就是這樣。
2. 應該設定nls_lang和終端使用一樣的編碼,這樣資料庫也能正確知道終端使用的編碼,就能正確得轉碼,就不大會把錯誤的編碼存進資料庫,情況b,c,d,e就是設錯了nls_lang才造成了問題。這裡面,還有種情況,就是不設nls_lang時,好像oracle缺省會把它當作和終端編碼一樣(需要確認)。
3. 盡量使得3個編碼都一樣,這樣就能避免編碼轉換造成的效能損失。
其實,不僅oracle,別的一些資料庫,甚至是一些程式設計工具,如jsp/servlet等都有類似的編碼體制,基本上都是終端(如jsp裡為編輯器),環境變數(jsp裡為pageencoding指令),伺服器端編碼(jsp為瀏覽器等);再比如oracle做imp時,終端編碼就為dmp包中的編碼(不一定為原資料庫編碼,因為有可能它在exp時,已經轉過碼了),環境變數編碼還是nls_lang,而服務端就是要實行imp的資料庫的編碼了。
有興趣的話,大家可以研究下mysql的字符集機制,它本質上還是使用三位一體的編碼機制,但劃分的更細。
from:[url]
oracle字符集問題總結
在進行web開發和oracle安裝的過程中經常有人對字符集搞不清楚,因此對此做一下總結。1.第乙個問題 字符集之間的區別是什麼呢?常見的字符集有 utf 8和gbk 1 gbk字符集 2 utf 8字符集 一般來說,國內的系統如果要儲存漢字,一般會選擇使用gbk字符集,如果是想做 等,全球可訪問的系...
oracle 檢視字符集與修改字符集
oracle字符集是乙個位元組資料的解釋的符號集合,有大小之分,有相互的包容關係。oracle 支援國家語言的體系結構允許你使用本地化語言來儲存,處理,檢索資料。它使資料庫工具,錯誤訊息,排序次序,日期,時間,貨幣,數字,和日曆自動適應本地化語言和平台。影響oracle資料庫字符集最重要的引數是nl...
oracle 檢視字符集與修改字符集
oracle字符集 oracle字符集是乙個位元組資料的解釋的符號集合,有大小之分,有相互的包容關係。oracle 支援國家語言的體系結構允許你使用本地化語言來儲存,處理,檢索資料。它使資料庫工具,錯誤訊息,排序次序,日期,時間,貨幣,數字,和日曆自動適應本地化語言和平台。影響oracle資料庫字符...