【发布时间】:2020-01-27 19:51:48
【问题描述】:
我想将 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)
但是,除非我明确地将 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)
我必须做些什么才能让 postgres 在我的数据库中使用 en-US-x-icu 作为默认排序而不显式设置 collate 参数?为什么即使我要求它按en-US-x-icu 排序,它还是按C 排序?
(对于它的价值:有问题的数据库是在 docker compose 上运行的 mdillon/postgis:10-alpine 图像。我真的不想离开 alpine 图像,但如果无法使用它,我可以。)
(更新:更改为非高山图像将排序更改为 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
)
(最终更新:我同意 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
【问题讨论】:
-
创建数据库时。也许您将 CREATE 语法与编码一起使用。 DB 编码优于服务器编码。
-
不,数据库不是使用编码创建的,它是一个“CREATE DATABASE mctapi”命令,没有其他选项
标签: sql database postgresql