PostgreSQL中的列排序在使用相同排序规则的macOS和Ubuntu之间是不同的

时间:2017-05-10 10:46:23

标签: postgresql collation

我在我的Mac和Ubuntu服务器上创建了一个包含UTF8编码和fr_FR排序规则的数据库,如下所示:

CREATE DATABASE my_database OWNER 'admin' TEMPLATE 'template0' ENCODING 'UTF8' LC_COLLATE 'fr_FR.UTF-8' LC_CTYPE 'fr_FR.UTF-8';

在两者上,我都查询了整理:

show lc_collate;

并获得:

fr_FR.UTF-8

然后,我尝试对相同的数据库进行排序,但没有获得相同的结果:

SELECT winery FROM usr_wines WHERE user_id=1 AND status=1 ORDER BY winery LIMIT 5;

1 - 在macOS上:

 a space before the a
A New record
Aa
Altesinoo
Aé

2-在Ubuntu 14.04上:

Aa
Aé
Altesino
A New Wine
 a space before a

在Ubuntu上,我安装了所需的语言环境并创建了一个新的排序规则:

CREATE COLLATION "fr_FR.utf8" (LOCALE = "fr_FR.utf8")

select * from pg_collation;

  collname  | collnamespace | collowner | collencoding | collcollate | collctype  
------------+---------------+-----------+--------------+-------------+------------
 default    |            11 |        10 |           -1 |             | 
 C          |            11 |        10 |           -1 | C           | C
 POSIX      |            11 |        10 |           -1 | POSIX       | POSIX
 C.UTF-8    |            11 |        10 |            6 | C.UTF-8     | C.UTF-8
 en_US      |            11 |        10 |            6 | en_US.utf8  | en_US.utf8
 en_US.utf8 |            11 |        10 |            6 | en_US.utf8  | en_US.utf8
 ucs_basic  |            11 |        10 |            6 | C           | C
 fr_FR      |          2200 |        10 |            6 | fr_FR.utf8  | fr_FR.utf8

在mac上,已经安装了fr_FR排序规则。

那么为什么这种分类差异呢?

Ubuntu上的另一个奇怪的问题:我试图在我的请求中强制整理:

SELECT winery FROM usr_wines WHERE user_id=1 AND status=1 ORDER BY winery COLLATE "fr_FR" LIMIT 5;

我得到了:

  

错误:整理" fr_FR"用于编码" UTF8"不存在

欢迎任何帮助。

1 个答案:

答案 0 :(得分:1)

COLLATE“C”会在所有平台上为您提供可预测的结果。 Additional collations may be available depending on operating system support。因此它的行为完全取决于操作系统。

https://www.postgresql.org/docs/current/static/collation.html

  

在所有平台上,名为default,C和POSIX的归类都是   可用。可以使用其他排序规则,具体取决于   操作系统支持。默认排序规则选择LC_COLLATE   和在数据库创建时指定的LC_CTYPE值。 C和   POSIX排序规则都指定“传统C”行为,仅在其中   ASCII字母“A”到“Z”被视为字母和排序   严格按字符代码字节值完成。

     

如果操作系统支持使用多个区域设置   在单个程序(newlocale和相关函数)中,然后当a   初始化数据库集群,initdb填充系统目录   pg_collat​​ion,基于在其上找到的所有语言环境的排序规则   当时的操作系统。例如,操作系统可能   提供名为de_DE.utf8的语言环境。然后initdb将创建一个   名为de_DE.utf8的collat​​ion用于编码具有LC_COLLATE的UTF8   并且LC_CTYPE设置为de_DE.utf8。它还将创建一个排序规则   .utf8标签剥离了名称。所以你也可以使用   名称为de_DE的排序规则,编写起来不那么麻烦   使名称减少编码依赖。但请注意,   初始的排序规则名称与平台有关。