我們的mysql使用latin1的預設字符集,也就是說,對漢字字段直接使用gbk內碼的編碼進行儲存,當需要對一些有漢字的字段進行拼音排序時(特別涉及到類似於名字這樣的字段時),預設無法通過order by關鍵字正確排序。
經過網上查詢,網上的辦法大多是針對使用utf8字符集的資料庫,主要的方法有:
1)直接轉換欄位為gbk,比如:
select * from table order by convert( chinese_field using gbk ) ;
或者乾脆將相應字段改為gbk字符集。
我在我的資料庫測試了上面的方法,或者直接按欄位排序,都不行,主要是排序結果不理想。
2)查表法
建立乙個新錶,用來儲存拼音聲母和使用該聲母的漢字首字的對應關係。然後寫乙個函式,每次排序時通過轉換為gbk再查表的方法得到字段內容首字的聲母的方法。
這個方法我也試了,太麻煩,而且針對我的資料庫,也不能正確排序。
後來,我查詢了漢字編碼的一些資料,發現gbk內碼編碼時本身就採用了拼音排序的方法(常用一級漢字3755個採用拼音排序,二級漢字就不是了,但考慮到人名等都是常用漢字,因此只是針對一級漢字能正確排序也夠用了)。根據這個原理,直接按欄位排序就應該可以的(我的資料庫使用latin1字符集,存的漢字本來就是gbk內碼),但我試了以後發現不行。參考上面方法2的查表法,我把字段內容轉換為16進製制編碼,再排,就ok了!
這就是最終的辦法:select * from table order by hex( chinese_field ) 簡單吧!
這是我的例子資料排序輸出的結果,如下圖:
附:漢字編碼方式簡介
ascii
ascii碼是7位編碼,編碼範圍是0x00-0x7f。ascii字符集包括英文本母、阿拉伯數字和標點符號等字元。其中0x00-0x20和0x7f共33個控制字元。
只支援ascii碼的系統會忽略每個位元組的最高位,只認為低7位是有效位。hz字元編碼就是早期為了在只支援7位ascii系統中傳輸中文而設計的編碼。早期很多郵件系統也只支援ascii編碼,為了傳輸中文郵件必須使用base64或者其他編碼方式。
gb2312
gb2312 是基於區位碼設計的,區位碼把編碼表分為94個區,每個區對應94個位,每個字元的區號和位號組合起來就是該漢字的區位碼。區位碼一般 用10進製數來表示,如1601就表示16區1位,對應的字元是「啊」。在區位碼的區號和位號上分別加上0xa0就得到了gb2312編碼。
區位碼中01-09區是符號、數字區,16-87區是漢字區,10-15和88-94是未定義的空白區。它將收錄的漢字分成兩級:第一級是常用漢字計 3755個,置於16-55區,按漢語拼音字母/筆形順序排列;第二級漢字是次常用漢字計3008個,置於56-87區,按部首/筆畫順序排列。一級漢字 是按照拼音排序的,這個就可以得到某個拼音在一級漢字區位中的範圍,很多根據漢字可以得到拼音的程式就是根據這個原理編寫的。
gb2312字符集中除常用簡體漢字字元外還包括希臘字母、日文平假名及片假名字母、俄語西里爾字母等字元,未收錄正體中文漢字和一些生僻字。可以用繁體漢字測試某些系統是不是只支援gb2312編碼。
gb2312的編碼範圍是0xa1a1-0x7e7e,去掉未定義的區域之後可以理解為實際編碼範圍是0xa1a1-0xf7fe。
euc-cn可以理解為gb2312的別名,和gb2312完全相同。
區位碼更應該認為是字符集的定義,定義了所收錄的字元和字元位置,而gb2312及euc-cn是實際計算機環境中支援這種字符集的編碼。hz和iso-2022-cn是對應區位碼字符集的另外兩種編碼,都是用7位編碼空間來支援漢字。區位碼和gb2312編碼的關係有點像 和。
gbkgbk 編碼是gb2312編碼的超集,向下完全相容gb2312,同時gbk收錄了unicode基本多文種平面中的所有cjk漢字。同 gb2312一樣,gbk也支援希臘字母、日文假名字母、俄語字母等字元,但不支援韓語中的表音字元(非漢字字元)。gbk還收錄了gb2312不包含的 漢字部首符號、豎排標點符號等字元。
gbk的整體編碼範圍是為0x8140-0xfefe,不包括低位元組是0×7f的組合。高位元組範圍是0×81-0xfe,低位元組範圍是0x40-7e和0x80-0xfe。
低位元組是0x40-0x7e的gbk字元有一定特殊性,因為這些字元占用了ascii碼的位置,這樣會給一些系統帶來麻煩。
有些系統中用0x40-0x7e中的字元(如「|」)做特殊符號,在定位這些符號時又沒有判斷這些符號是不是屬於某個 gbk字元的低位元組,這樣就會造成錯誤判斷。在支援gb2312的環境下就不存在這個問題。需要注意的是支援gbk的環境中小於0x80的某個位元組未必就 是ascii符號;另外就是最好選用小於0×40的ascii符號做一些特殊符號,這樣就可以快速定位,且不用擔心是某個漢字的另一半。big5編碼中也 存在相應問題。
cp936和gbk的有些許差別,絕大多數情況下可以把cp936當作gbk的別名。
gb18030
gb18030編碼向下相容gbk和gb2312,相容的含義是不僅字元相容,而且相同字元的編碼也相同。gb18030收錄了所有unicode3.1中的字元,包括中國少數民族字元,gbk不支援的韓文本元等等,也可以說是世界大多民族的文字元號都被收錄在內。
gbk和gb2312都是雙位元組等寬編碼,如果算上和ascii相容所支援的單位元組,也可以理解為是單位元組和雙位元組混合的變長編碼。gb18030編碼是變長編碼,有單位元組、雙位元組和四位元組三種方式。
gb18030 的單位元組編碼範圍是0x00-0x7f,完全等同與ascii;雙位元組編碼的範圍和gbk相同,高位元組是0x81-0xfe,低位元組的編碼範圍是0x40 -0x7e和0x80-fe;四位元組編碼中第
一、三位元組的編碼範圍是0x81-0xfe,二、四位元組是0x30-0x39。
windows 中cp936**頁使用0x80來表示歐元符號,而在gb18030編碼中沒有使用0x80編碼位,用其他位置來表示歐元符號。這可以理解為是 gb18030向下相容性上的一點小問題;也可以理解為0x80是cp936對gbk的擴充套件,而gb18030只是和gbk相容良好。
unicode
每一種語言的不同的編碼頁,增加了那些需要支援不同語言的軟體的複雜度。因而人們制定了乙個世界標準,叫做unicode。unicode為每個字元提供 了唯一的特定數值,不論在什麼平台上、不論在什麼軟體中,也不論什麼語言。也就是說,它世界上使用的所有字元都列出來,並給每乙個字元乙個唯一特定數值。
unicode的最初目標,是用1個16位的編碼來為超過65000字元提供對映。但這還不夠,它不能覆蓋全部歷史上的文字,也不能解決傳輸的問題 (implantation head-ache's),尤其在那些基於網路的應用中。已有的軟體必須做大量的工作來程式16位的資料。
因 此,unicode用一些基本的保留字元制定了三套編碼方式。它們分別是utf-8,utf-16和utf-32。正如名字所示,在utf-8中,字元是 以8位序列來編碼的,用乙個或幾個位元組來表示乙個字元。這種方式的最大好處,是utf-8保留了ascii字元的編碼做為它的一部分,例如,在utf-8 和ascii中,「a」的編碼都是0x41.
utf-16和utf-32分別是unicode的16位和32位編碼方式。考慮到最初的目的,通常說的unicode就是指utf-16。在討論unicode時,搞清楚哪種編碼方式非常重要。
utf-8
gbk的文字編碼是用雙位元組來表示的,即不論中、英文本元均使用雙位元組來表示,為了區分中文,將其最高位都設定成1。gbk包含全部中文字元,是國家編碼,通用性比utf8差,不過utf8占用的資料庫比gbd大。
gbk、gb2312等與utf8之間都必須通過unicode編碼才能相互轉換:
gbk、gb2312→unicode→utf8
utf8→unicode→gbk、gb2312
對於乙個**、論壇來說,如果英文本元較多,則建議使用utf-8節省空間。不過現在很多論壇的外掛程式一般只支援gbk。
windows的ansi
不同的國家和地區制定了不同的標準,由此產生了 gb2312, big5, jis 等各自的編碼標準。這些使用 2 個位元組來代表乙個字元的各種漢字延伸編碼方式,稱為 ansi 編碼。在簡體中文系統下,ansi 編碼代表 gb2312 編碼,在日文作業系統下,ansi 編碼代表 jis 編碼。
不同 ansi 編碼之間互不相容,當資訊在國際間交流時,無法將屬於兩種語言的文字,儲存在同一段 ansi 編碼的文字中。
分享到:
2009-08-11 21:07
瀏覽 808
MySQL按照漢字的拼音排序,mysql漢字排序
按照漢字的拼音排序,用的比較多是在人名的排序中,按照姓氏的拼音字母,從a到z排序 如果儲存姓名的字段採用的是gbk字符集,那就好辦了,因為gbk內碼編碼時本身就採用了拼音排序的方法 常用一級漢字3755個採用拼音排序,二級漢字就不是了,但考慮到人名等都是常用漢字,因此只是針對一級漢字能正確排序也夠用...
mysql 根據漢字首字母排序
在開發中,總會遇到各種 問題,排序的時候要按照中文的首字母排序,這裡就需要我們根據字元的編碼集將漢字排序。在mysql資料庫中,存在很多種字符集儲存方式,比如utf8 latin1等,所以對排序也要根據不同字符集處理。1 如果資料庫表字段的字元編碼是latin1 swedish ci select ...
mysql 記憶體排序 mysql 排序過程
order by sql city為索引 select city,name,age from zx where city 杭州 order by name limit 1000 sort buffer mysql進行排序的時候會分配每個執行緒分配一塊記憶體用於排序 全欄位排序 過程1.首先會根據要查...