区分大小写不一致

Héc*_*tor 3 postgresql collation order-by

我正在尝试学习和理解排序规则以及 postgresql 如何比较和排序字符串,但我发现了一个不协调的地方,我不知道我错过了什么。

查询:

SELECT datname, datcollate FROM pg_database;
Run Code Online (Sandbox Code Playgroud)

返回我的所有数据库都使用 en_GB.UTF-8 排序规则。

和查询:

SELECT table_schema, 
   table_name, 
   column_name,
   collation_name
FROM information_schema.columns
WHERE collation_name is not null
ORDER BY table_schema,
     table_name,
     ordinal_position;
Run Code Online (Sandbox Code Playgroud)

返回所有列都具有“C”排序规则,这意味着(根据我的研究)未指定排序规则。所以,我认为使用了数据库排序规则,不是吗?

编辑:我的错误就在这里。前面的查询不会返回所有列的结果,只会返回那些不collation_name为 null 的列,并且具有 null 排序规则的列是继承 DB 排序规则的列。所以我认为 foo.bar 列有C排序规则,但null事实上确实如此。

好吧,当我运行查询时,不一致的情况出现了:

SELECT "name" FROM foo.bar ORDER BY "name" ASC;
Run Code Online (Sandbox Code Playgroud)

其中“name”列数据类型是文本,foo.bar 是用户创建的 schema.table 组合。结果是像人类一样按字母顺序排列。从a/A到Z/z,无论是大写还是小写。

但是如果我运行以下查询:

SELECT "table_name"
FROM information_schema.tables
WHERE
    "table_name" ~ 'some_pattern'
    AND table_schema = 'foo'
    AND table_type = 'BASE TABLE'
ORDER BY "table_name" ASC;
Run Code Online (Sandbox Code Playgroud)

它以类似机器的方式对结果进行排序,逐字节比较,因此将大写字母排在小写字母前面。

为什么会有这样的差异呢?我已经看到“table_name”列数据类型不是“text”而是“name”,但我找不到它是否有关系。

将数据库排序规则设置为 en_GB.UTF-8 不足以以人类的方式比较文本吗?

谢谢你的时间。

Lau*_*lbe 5

PostgreSQL 中的排序规则确定如下(简化,详细信息请参阅文档):

\n
    \n
  • 如果有明确的COLLATE子句,则确定排序规则

    \n
  • \n
  • 否则,如果表列是使用特定排序规则定义的,则使用该排序规则

    \n
  • \n
  • 如果该列未使用排序规则定义(它具有 \xe2\x80\x9c 默认排序规则\xe2\x80\x9d),则使用数据库排序规则。

    \n
  • \n
\n

现在该列bar.name未使用排序规则定义,因此en_GB.UTF-8已使用。

\n

information_schema.columns具有类型 的列information_schema.sql_identifier,它是数据类型 的域name,始终使用C排序规则。因此,在该查询中,大写字母会排在小写字母之前。

\n

要改变这一点,您应该显式指定排序规则:

\n
ORDER BY table_schema COLLATE "en_GB.UTF-8",\n         table_name COLLATE "en_GB.UTF-8",\n         ordinal_position;\n
Run Code Online (Sandbox Code Playgroud)\n