Ruby PG 關(guān)于一次漢字排序問題解決辦法

image.png

參考鏈接:

  1. 在PG中存儲中文,現(xiàn)在大家的典型解決方法是用UTF8做數(shù)據(jù)庫編碼粘茄,但是用UTF8作數(shù)據(jù)庫編碼有一個問題签舞,就是中文排序的問題。

在PG中柒瓣,缺省的時候是按照編碼排序的儒搭,也就是按照UTF8的編碼對字段排序,但是芙贫,UTF8本身的編碼順序和人們習(xí)慣的中文的發(fā)音的拼音順序完全不同搂鲫,因而排序完全不是期望的拼音排序。那么如何解決呢磺平?

眾所周知魂仍,GBK編碼是按照拼音發(fā)音順序排序的,因此拣挪,解決方法之一就是把UTF8編碼轉(zhuǎn)換成GBK編碼擦酌。在這方面,PG提供了很好的支持函數(shù)菠劝。

PG提供的一些轉(zhuǎn)換函數(shù)

PG提供了很好的編碼轉(zhuǎn)換函數(shù):convert()赊舶,使用這個函數(shù),我們可以有效地把UTF8編碼轉(zhuǎn)換成GBK編碼赶诊。比如笼平,要把UTF8編碼轉(zhuǎn)換成GBK編碼:

select convert('UTF8編碼字串或字段' using utf8_to_gbk);

這樣就可以了,那么舔痪,是不是我們可以這樣實(shí)現(xiàn)GBK的讀音序編碼呢:

select * from table order by convert( column_need_to_sort_in_utf8 using utf8_to_gbk);

但是實(shí)際上試驗(yàn)的結(jié)果寓调,仍然不對,這是為什么呢锄码?

如何解決

原因在于捶牢,對于文本字段(text, varchar, char類型的字段),PG是使用底層OS的locale相關(guān)的函數(shù)進(jìn)行字符串比較的巍耗,眾所周知,排序的一個重要的事情就是需要字符串比較函數(shù)(幾乎所有的排序算法都涉及大于渐排、小于炬太、等于等過程)。而遺憾的是驯耻,因?yàn)楦鞣N原因(國家沒有投入是一個重要原因)亲族,在各種OS上的locale相關(guān)的函數(shù)集(比如 stroll)炒考,對漢字的排序比較都不是很標(biāo)準(zhǔn);也不是很正確霎迫。

怎么解決呢斋枢?從根本分析入手,就是要讓PG不使用OS的locale相關(guān)的東西知给,這樣瓤帚,解法之一是 initdb 的時候,使用C做locale涩赢,這個時候PG會用strcmp戈次,而不是stroll來比較字串大小。但是這樣也不一定很好筒扒,因?yàn)閟trcmp有時候在某些特殊的編碼的時候也會有些問題怯邪,并且,我們很多時候也需要locale花墩,比如在中文的全文索引的時候悬秉。

那么,有什么辦法讓PG一定用類似memcp(1)這樣的接口來比較數(shù)據(jù)么冰蘑?

答案當(dāng)然是有的:還記得PG有個數(shù)據(jù)類型是二進(jìn)制數(shù)據(jù)類型么和泌?它就是BYTEA,在PG中懂缕,所有的變長類型:TEXT允跑、BYTEA、 VARCHAR等的底層結(jié)構(gòu)都是一樣的搪柑,但是每個類型在SQL子句中調(diào)用的OS處理函數(shù)不同聋丝,比如BYTEA就是使用memcp(1)進(jìn)行排序的比較的,因此工碾,我們可以想辦法把TEXT的類型轉(zhuǎn)換成BYTEA進(jìn)行ORDER BY弱睦,這樣就可以即使用locale,又繞開stroll的限制渊额。

因?yàn)闆]有內(nèi)置的TEXT到BYTEA的轉(zhuǎn)換函數(shù)况木,我們需要自己做一個:

CREATE OR REPLACE FUNCTION text2bytea(text)

RETURNS bytea AS

$BODY$

begin

return $1;

end; $BODY$

LANGUAGE plpgsql immutable;

這個函數(shù)很簡單,利用了PG提供的text_in()和bytea_out的輸入輸出轉(zhuǎn)換函數(shù)旬迹,直接生成BYTEA的數(shù)據(jù)火惊。

于是,我們可以這樣進(jìn)行中文的語音排序了:

select * from table order by text2bytea(convert(column_need_to_sort_in_utf8 using utf8_to_gbk));

  1. http://francs3.blog.163.com/blog/static/405767272013521112126587/

  2. http://blog.csdn.net/u9999/article/details/7243613

  3. http://www.codeweblog.com/pg%E5%AD%97%E7%AC%A6-%EF%BB%BF%E4%BD%BF%E7%94%A8collation%E8%AE%BE%E7%BD%AE%E6%8E%92%E5%BA%8F%E8%A7%84%E5%88%99/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奔垦,一起剝皮案震驚了整個濱河市屹耐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌椿猎,老刑警劉巖惶岭,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寿弱,死亡現(xiàn)場離奇詭異,居然都是意外死亡按灶,警方通過查閱死者的電腦和手機(jī)症革,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鸯旁,“玉大人噪矛,你說我怎么就攤上這事∠勰叮” “怎么了摩疑?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長畏铆。 經(jīng)常有香客問我雷袋,道長,這世上最難降的妖魔是什么辞居? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任楷怒,我火速辦了婚禮,結(jié)果婚禮上瓦灶,老公的妹妹穿的比我還像新娘鸠删。我一直安慰自己,他們只是感情好贼陶,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布刃泡。 她就那樣靜靜地躺著,像睡著了一般碉怔。 火紅的嫁衣襯著肌膚如雪烘贴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天撮胧,我揣著相機(jī)與錄音桨踪,去河邊找鬼。 笑死芹啥,一個胖子當(dāng)著我的面吹牛锻离,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播墓怀,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼汽纠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了傀履?” 一聲冷哼從身側(cè)響起疏虫,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后卧秘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡官扣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年翅敌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惕蹄。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡蚯涮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卖陵,到底是詐尸還是另有隱情遭顶,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布泪蔫,位于F島的核電站棒旗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏撩荣。R本人自食惡果不足惜铣揉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望餐曹。 院中可真熱鬧逛拱,春花似錦、人聲如沸台猴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饱狂。三九已至曹步,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嗡官,已是汗流浹背箭窜。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留衍腥,地道東北人磺樱。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像婆咸,于是被迫代替她去往敵國和親竹捉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容