对于我的数据库,我想要自然的('A2'<'A12'), case-insensitive sorting, so for testing I created a new collation with
CREATE COLLATION tomscollation (provider = icu, locale = 'de-u-kn-true-ks-level2');
我的最终目标是使用这样的排序规则作为整个数据库的默认排序规则,以便每个文本列或索引默认使用它。
此消息来源指出,对于 PostgreSQL 15,数据库级别尚不支持非确定性排序规则。 这就是我的困惑开始的地方。查看我的整理,数据库说它是确定性的(见屏幕截图)。然而,文档说只有字节顺序排序规则可以是确定性的,但我的显然不是字节顺序。
所以我在这里错过了什么? 为什么我能够创建以下数据库以及我可能不知道的副作用是什么?
CREATE DATABASE tomsdb TEMPLATE template0 LOCALE_PROVIDER icu ICU_LOCALE 'de-u-kn-true-ks-level2'
kn=true
表示 Unicode Locale Extension 数字顺序将是默认值。
“数据库级别尚不支持非确定性排序规则。”意味着默认情况下,
select 'a' = 'A';
将返回 false。
CREATE DATABASE tomsdb TEMPLATE template0
LOCALE_PROVIDER icu
ICU_LOCALE 'de-u-kn-true-ks-level2'
LOCALE 'de_DE.utf8'
;
select 'a1' = 'A1'
union all
select 'a2' > 'A12'
union all
select 'A2' > 'A12';
它返回:
?column?
----------
f
f
f
(3 rows)
所以在数据库级别上,kn=true 确实按预期工作。但是
ks-level2
默认情况下应该使 select 'a1' = 'A1'
返回 true.
所以你需要创建排序规则来进行不区分大小写的排序,如下所示:
CREATE COLLATION case_insensitive (
provider = icu, locale = 'und-u-ks-level2', deterministic = false);
select 'a1' = 'A1' COLLATE case_insensitive;
de-u-kn-true-ks-level2
根据定义not确定性。如果您在需要确定性排序规则的上下文中使用非确定性排序规则(例如作为数据库排序规则,或者如果您将排序规则定义为DETERMINISTIC = TRUE
),PostgreSQL 将使用memcmp
打破平局如果两个字符串比较相等,但不相同。
这意味着,例如,如果您对数据库使用该排序规则,您将得到
'A1' < 'a1'
,因为 memcmp
将 A
的较低 ASCII 值排在 a
的较高 ASCII 值之前。
参见
varstr_cmp()
中src/backend/utils/adt/varlena.c
的代码:
/* Break tie if necessary. */
if (result == 0 &&
(!mylocale || mylocale->deterministic))
result = strcmp(a1p, a2p);
由于您在评论中提出:如果您将排序规则标记为
DETERMINISTIC
,则不同的字符串永远不会比较相等。