与 postgresql 的奇怪排序

Strange collation with postgresql

我注意到 postgresql-9.5 有一个奇怪的整理问题,因为它向 Python 脚本提供了不同的输出。据我了解,通常在排序时从左到右一次比较一个字符:

select 'ab' < 'ac';
 t

select 'abX' < 'ac';
 t

因此,如果您将 'X' 添加到上面的左侧字符串,则无关紧要。

所以我很惊讶这不适用于 space 和破折号之间的比较:

select 'a ' < 'a-';
 t

select 'a X' < 'a-';
 f

这是一个错误还是有什么办法解决这个问题;我希望上面的最后一条语句也 return 为真。


[接受@laurenz-albe 的回答后编辑]

show lc_collate;
 en_US.UTF-8

如果我在 Python 中按 unicode 进行排序,我会得到类似的结果,所以我认为这不是 postgresql 中的错误,而是 unicode 归类规范中的错误!:

>>> import locale; locale.setlocale(locale.LC_ALL, "")
'en_US.UTF-8'
>>> l = ['ac', 'ab']; sorted(l) == sorted(l, cmp=locale.strcoll)
True
>>> l = ['ac', 'abX']; sorted(l) == sorted(l, cmp=locale.strcoll)
True
>>> l = ['ac', 'abX']; sorted(l) == sorted(l, cmp=locale.strcoll)
True
>>> l = ['a-', 'a X']; sorted(l) == sorted(l, cmp=locale.strcoll)
False
>>> sorted(l),  sorted(l, cmp=locale.strcoll)
(['a X', 'a-'], ['a-', 'a X'])

使用排序规则比较字符。您可以使用 SQL 命令

SHOW lc_collate;

查看您的默认排序规则。

PostgreSQL 使用操作系统的排序规则,因此比较的结果通常取决于操作系统。

要强制按字节进行 ASCII 比较,请使用 C 排序规则

test=> SELECT 'a X' COLLATE "C" < 'a-';
 ?column?
----------
 t
(1 row)

或字节比较运算符

test=> SELECT 'a X' ~<~ 'a-';
 ?column?
----------
 t
(1 row)