2011-02-10 86 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语言环境感知排序功能实现的。