lli*_*lib 3 sql database postgresql
我想将 postgres 设置为en-US-x-icu默认按排序规则排序,因此我将LC_CTYPE和LC_COLLATE环境变量设置为该值。Postgres 似乎看到了它们,并说它正在使用该排序规则:
:mctapi=# select datname, datcollate, datctype from pg_database where datname='mctapi';
datname | datcollate | datctype
---------+-------------+-------------
mctapi | en-US-x-icu | en-US-x-icu
:mctapi=# show lc_collate;
lc_collate
-------------
en-US-x-icu
(1 row)
:mctapi=# show lc_ctype;
lc_ctype
-------------
en-US-x-icu
(1 row)
Run Code Online (Sandbox Code Playgroud)
但是,除非我明确设置en-US-x-icu为排序规则,否则我会得到C排序规则:
:mctapi=# select distinct organization_name from plans order by organization_name limit 5;
organization_name
------------------------------------------
AMH Health
ATRIO Health Plans
Aetna Medicare
AgeRight Advantage
AgeRight Advantage Health Plan (HMO SNP)
(5 rows)
:mctapi=# select distinct organization_name collate "en-US-x-icu" from plans order by organization_name limit 5;
organization_name
------------------------------------------
Aetna Medicare
AgeRight Advantage
AgeRight Advantage Health Plan (HMO SNP)
Allwell
AMH Health
(5 rows)
:mctapi=# select distinct organization_name collate "C" from plans order by organization_name limit 5;
organization_name
------------------------------------------
AMH Health
ATRIO Health Plans
Aetna Medicare
AgeRight Advantage
AgeRight Advantage Health Plan (HMO SNP)
(5 rows)
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能让 postgresen-US-x-icu在我的数据库中用作默认排序而不显式设置 collate 参数?C即使我已经要求它排序,为什么它仍然排序en-US-x-icu?
(对于它的价值:有问题的数据库是mdillon/postgis:10-alpine在 docker compose 上运行的图像。我真的不想离开高山图像,但如果无法使用它,我可以。)
(更新:更改为非高山图像将排序更改为 en_US.UTF8,如下面的 postgres docker 图像文档中所述,并修复了此表的排序顺序。我仍然想知道为什么我的 LC_COLLATE 设置没有不过在 alpine 中更改整理顺序,因为我宁愿使用该图像)
(更新 2:数据库是在没有编码选项的情况下创建的,我没有手动更新pg_database,我唯一改变的是LC_CTYPE和LC_COLLATE环境变量。
这个版本的 postgres 是用 编译的--with-icu,你可以在这里看到:https : //github.com/docker-library/postgres/blob/master/10/alpine/Dockerfile#L113和https://www.postgresql.org /docs/10/collation.html#COLLATION-MANAGING在我看来当然是说 ICU 语言环境应该可以在我的 postgres 版本中使用。
如果我取消设置LC_COLLATE并LC_CTYPE重新创建我的数据库,它的 collate 和 ctype 值可能是相关的en_US.UTF8,但是包含该数据库的 Alpine 图像中不存在该区域设置,从而导致这种情况:
:mctapi=# select datname, datcollate, datctype from pg_database where datname='mctapi';
datname | datcollate | datctype
---------+------------+------------
mctapi | en_US.utf8 | en_US.utf8
(1 row)
:mctapi=# select distinct organization_name collate "en_US.utf8" from plans order by organization_name limit 5;
ERROR: collation "en_US.utf8" for encoding "UTF8" does not exist
Run Code Online (Sandbox Code Playgroud)
)
(最后更新:我同意 Laurenz 关于 alpine 上 postgres 在语言环境方面的普遍破坏,我真的很感激他对这个问题的看法。我仍然不明白为什么 ICU 不能作为 LC_COLLATE 工作,或者为什么它可以明确提及时可以工作,但我刚刚接受了我不能使用 alpine docker 映像并已转移到基于 debian 的映像。)
参考:
1:https : //www.postgresql.org/docs/10/locale.html
2:https : //www.postgresql.org/docs/10/collation.html
3:https : //www.postgresql.org/docs/10/sql-expressions.html#SQL-SYNTAX-COLLATE-EXPRS
4:https : //wiki.postgresql.org/wiki/FAQ#Why_do_my_strings_sort_incorrectly.3F
5:https : //github.com/docker-library/docs/tree/master/postgres#locale-customization
除了 C 库的排序规则之外,您不能在CREATE DATABASE. 这是一个未公开的限制,可能会在 v13 中取消。作为参考,请参阅此和此线程。
因此,起初我很惊讶您设法创建了该数据库,因为您的归类是 ICU 归类,通常只能通过单独的 ICU 库获得。
我发现了一个Silverstripe 问题,它抱怨完全相同的事情,所以至少你并不孤单。那里的讨论没有任何意义,因为他们似乎对 Alpine Linux 和 PostgreSQL 都不太了解。
根据您的评论进行的进一步调查表明,Alpine Linux 不使用 glibc,而是使用musl作为 C 库。似乎 musl 对排序规则的实现还没有完全完成,至少我在路线图中找到了这一点:
musl 1.2.0 的里程碑目标
已经确定了构成“musl 1.2.0”的以下暂定目标。目前没有 1.2.0 的预计发布日期。
[...] - 改进的语言环境和多语言支持
LC_COLLATE支持除简单代码点顺序之外的整理顺序
这似乎解释了你的经历。
使用具有工作排序规则的不同 Linux 发行版是前进的方向。