2011-02-10 54 views
2

我有一個用da_DK.utf8語言環境創建的PostgreSQL 8.4數據庫。PostgreSQL在訂購時忽略破折號

dbname=> show lc_collate; 
lc_collate 
------------ 
da_DK.utf8 
(1 row) 

當我選擇,我在字符順序變化的專欄中,我得到一個奇怪的行爲IMO表的東西。當訂購的結果PostgreSQL的忽略前綴的價值破折號,例如:

select name from mytable order by name asc; 

可能返回類似

name 
---------------- 
Ad... 
Ae... 
Ag... 
- Ak.... 
At.... 

破折號前綴似乎被忽略。

我可以通過轉換列在訂貨時解決此問題爲latin1:

select name from mytable order by convert_to(name, 'latin1') asc; 

的我得到預期的結果爲:

name 
---------------- 
- Ak.... 
Ad... 
Ae... 
Ag... 
At.... 

爲什麼破折號前綴得到默認被忽略掉?這種行爲可以改變嗎?

+0

什麼操作系統您使用的?它在Windows 7上正常工作,不需要convert_to()。 – 2011-02-10 09:56:39

+0

我正在運行的Ubuntu服務器10.10和PostgreSQL版本8.4.7是精確的 – HakonB 2011-02-10 10:12:28

回答

1

解決方法,將在我的具體情況下工作是用感嘆號替換破折號。我碰巧知道我永遠不會得到感嘆號,它會在任何字母或數字前排序。

select name from mytable order by translate(name, '-', '!') asc 

這肯定會影響性能,所以我可能會考慮進行排序創建一個特殊的列,但我真的不喜歡,要麼......

3

這是因爲da_DK.utf8區域設置以這種方式定義它。 Linux區域感知實用程序,例如sort也可以像這樣工作。

如果convert_to(name, 'latin1')找到一個不是拉丁字符1的字符集,例如,它會中斷,因此它不是一個好的解決方法。

您可以使用order by convert_to(name, 'SQL_ASCII'),它會忽略區域設置的排序並簡單地使用字節值。


醜陋的黑客編輯:

order by 
    (
    ascii(name) between ascii('a') and ascii('z') 
    or ascii(name) between ascii('A') and ascii('Z') 
    or ascii(name)>127 
), 
    name; 

這將排序與ASCII非字母開頭的第一個東西。這非常醜陋,因爲在字符串中進一步排序會表現得很奇怪,但它對你來說足夠好。

0

我不知道如何看起來像荷蘭語的排序規則,但對於波蘭特殊字符如空格,破折號等在大多數字典中排序時並不「計數」。一些好的排序例程也會這樣做,並忽略這些特殊字符。可能在荷蘭有類似的規則,這個規則是通過Ubuntu語言環境感知排序功能實現的。