【发布时间】:2013-07-01 18:00:13
【问题描述】:
是否可以通过包含 [](),; 等字符的标题字段对 PostgreSQL 查询的结果进行排序,但忽略这些标点符号并仅按文本字符排序?
我已阅读有关更改数据库排序规则或语言环境的文章,但没有找到任何关于如何在现有数据库上按列执行此操作的明确说明。这甚至可能吗?
【问题讨论】:
标签: postgresql sql-order-by postgresql-9.1 collation
是否可以通过包含 [](),; 等字符的标题字段对 PostgreSQL 查询的结果进行排序,但忽略这些标点符号并仅按文本字符排序?
我已阅读有关更改数据库排序规则或语言环境的文章,但没有找到任何关于如何在现有数据库上按列执行此操作的明确说明。这甚至可能吗?
【问题讨论】:
标签: postgresql sql-order-by postgresql-9.1 collation
您可以在ORDER BY 子句中使用regexp_replace() 和'[^a-zA-Z]' 模式,但它只能识别纯ASCII 字母。最好使用class shorthand '\W',它可以识别您的语言环境中的其他非ASCII字母,例如äüóèß等。
或者您可以即兴创作并“借助 unaccent() 函数将所有带有变音符号元素的字符标准化为它们的基本形式。考虑这个小演示:
SELECT *
, regexp_replace(x, '[^a-zA-Z]', '', 'g')
, regexp_replace(x, '\W', '', 'g')
, regexp_replace(unaccent(x), '\W', '', 'g')
FROM (
SELECT 'XY ÖÜÄöüäĆČćč€ĞğīїıŁłŃńŇňŐőōŘřŠšŞşůŽžż‘´’„“”–—[](),;.:̈� XY'::text AS x) t
->SQLfiddle for Postgres 9.2.
->SQLfiddle for Postgres 9.1.
正则表达式代码已在 9.2 版本中更新。我假设这是在 9.2 中改进处理的原因,其中示例中的所有字母字符都匹配,而 9.1 只匹配一些。
unaccent() 由附加模块unaccent 提供。运行:
CREATE EXTENSION unaccent;
每个数据库使用一次(Postgres 9.1+,旧版本使用different technique)。
您必须知道 Postgres 依赖于底层操作系统的语言环境(包括排序规则)。排序顺序由您选择的区域设置或更具体的LC_COLLATE 控制。更多相关答案:
String sort order (LC_COLLATE and LC_CTYPE)
有plans to incorporate collation support into Postgres directly,但目前不可用。
许多语言环境忽略了您描述的用于对字符数据进行开箱即用排序的特殊字符。如果您的系统中安装了提供所需排序顺序的语言环境,则可以在 Postgres 9.1 或更高版本中临时使用它:
SELECT foo FROM bar ORDER BY foo COLLATE "xy_XY"
要查看当前 Postgres 安装中已安装和可用的排序规则:
SELECT * FROM pg_collation;
不幸的是,除非您破解源代码,否则无法定义您自己的自定义排序规则。
排序规则通常受某个国家/地区使用的语言规则的约束。如果还有电话簿的话,电话簿的排序顺序会在里面……你的操作系统提供了它们。
例如,在 Debian Linux 中,您可以使用:
locale -a
显示所有生成的语言环境。并且:
dpkg-reconfigure locales
作为 root 用户(多种方式之一)生成/安装更多。
【讨论】:
如果您想在一个特定查询中进行此排序,您可以
ORDER BY regexp_replace(title, '[^a-zA-Z]', '', 'g')
它将从字符串中删除所有非A-Z,并按结果字段排序。
【讨论】: