Linux 和 Mac 上 PostgreSQL 14 排序规则行为的差异

Chr*_*lis 5 postgresql collation ubuntu mac-os-x

我在 Mac 和 Ubuntu 服务器上安装了 PostgreSQL,如下所示:

atsweb=# select version();
                                                      version                                                      
-------------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.6 on x86_64-apple-darwin20.6.0, compiled by Apple clang version 12.0.0 (clang-1200.0.32.29), 64-bit
(1 row)
Run Code Online (Sandbox Code Playgroud)
atsweb=# select version();
                                                               version                                                                
--------------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 14.6 (Ubuntu 14.6-0ubuntu0.22.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0, 64-bit
(1 row)
Run Code Online (Sandbox Code Playgroud)

它们具有相同的数据库、排序规则和编码:

atsweb=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 atsweb    | atsweb   | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(4 rows)
Run Code Online (Sandbox Code Playgroud)

但是,当我en_US.UTF-8在 Ubuntu 上指定排序规则时,出现错误:

atsweb=# select 'test last name' < 'test2 last name' COLLATE "en_US.UTF8";
ERROR:  collation "en_US.UTF8" for encoding "UTF8" does not exist
LINE 1: select 'test last name' < 'test2 last name' COLLATE "en_US.U...
Run Code Online (Sandbox Code Playgroud)

指定en_US排序规则在 Ubuntu 上有效,但是当我运行如下所示的完全相同的语句时,结果不同:

乌班图:

atsweb=# select 'test last name' < 'test2 last name' COLLATE "en_US";
 ?column? 
----------
 f
(1 row)
Run Code Online (Sandbox Code Playgroud)

苹果:

atsweb=# select 'test last name' < 'test2 last name' COLLATE "en_US";
 ?column? 
----------
 t
(1 row)
Run Code Online (Sandbox Code Playgroud)

这是我的配置错误还是某个地方的错误?有关如何解决此问题的任何线索吗?

更新:

尝试使用 postgresql-14.6 docker 镜像并得到与 Ubuntu 中完全相同的结果。这是否意味着Mac安装有问题?在“en_US”或“en_US.UTF-8”排序规则下,“test2姓氏”是否应该位于“test姓氏”之前?

Lau*_*lbe 5

您可能需要通过运行以下命令来在 Ubuntu 上生成相应的区域设置root

locale-gen en_US.UTF-8
Run Code Online (Sandbox Code Playgroud)

之后,您必须以超级用户身份在 PostgreSQL 中创建新的排序规则:

SELECT pg_import_system_collations('pg_catalog');
Run Code Online (Sandbox Code Playgroud)


Chr*_*lis 0

显然,正如这个这个答案所指出的,除了“C”排序之外,排序规则是依赖于操作系统的,即使它们命名相同,也可能会有所不同。甚至有一个开放的票证指出 Mac 中的实现已被破坏。由于我只需要出于测试目的而使排序保持一致,因此我修改了测试来解决此问题。