为什么我的字符串排序不正确?
为什么我的字符串排序不正确?
首先,确保您使用的是要使用的区域设置。使用SHOW lc_collate
显示当前的数据库级别的区域设置。如果您在使用每列排序规则,请检查这些排序规则。如果一切都是您想要的,请继续阅读。
PostgreSQL 使用libc
库的区域能力来对字符串进行排序。因此,如果字符串的排序顺序不是您所期望的,则问题可能出在libc
库中。您可以使用文本文件上的sort
实用程序验证libc
库的排序思路,例如:
LC_COLLATE="zh_CN.UTF-8" sort testfile.txt
如果这导致与 PostgreSQL 相同的顺序,那么问题来自于 PostgreSQL 之外。
PostgreSQL 偏离了libc
的行为,因为它通过按字节顺序对字符串进行排序而打破了联系。这在实践中应该很少产生影响,并且当用户抱怨排序顺序时通常不是问题的根源,但它可能会影响例如组合和预组合的 Unicode 字符混合的情况。
如果问题出在libc
库中,则必须与操作系统维护人员一起解决。但是请注意,即使确认libc
库的区域设置定义中存在实际错误,但更有可能的是libc
库是正确的,其中“正确”意味着它遵循一些公认的国际或国家标准。您可能期望对语言的排序规则的多种同样有效的解释之一。
用户经常反馈的问题包括:
-
空格和特殊字符:排序算法通常在多个传递中工作。我们可以这样简单地理解:首先,比较所有字母,忽略空格和标点符号;然后,将空格和标点符号进行比较以排除影响。如果不更改区域设置定义本身,就不可能更改这个排序的行为(即使这样也很困难)。您可能需要稍微调整数据以避免此问题。例如,如果要对名称字段进行排序,则可以将该字段拆分为名字和姓氏字段,避免中间的空格。
-
大小写:除
C
以外的区域设置通常将大写和小写字母排序在一起。所以顺序将是类似于 “a A b B c C …",而不是基于 ASCII 字节值的排序给出 “A B C … a b c …"。这是正确的。 -
它不是按 ASCII/字节顺序排列的。不是的,也不应该。ASCII 是一种编码,而不是排序顺序。如果需要,可以使用
C
区域设置,但这样就失去了根据具体语言对非 ASCII 字符进行排序的能力。