加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

PostgreSQL支持“重音不敏感”的排序规则吗?

发布时间:2020-12-13 16:51:40 所属栏目:百科 来源:网络整理
导读:在Microsoft SQL Server中,可以指定“重音不敏感”归类(对于数据库,表或列),这意味着它可能用于查询 SELECT * FROM users WHERE name LIKE 'Jo?o' 找到具有Joao名称的行。 我知道,可以使用unaccent_string contrib函数从PostgreSQL中的字符串剥离重音,
在Microsoft SQL Server中,可以指定“重音不敏感”归类(对于数据库,表或列),这意味着它可能用于查询
SELECT * FROM users WHERE name LIKE 'Jo?o'

找到具有Joao名称的行。

我知道,可以使用unaccent_string contrib函数从PostgreSQL中的字符串剥离重音,但我想知道PostgreSQL是否支持这些“重音不敏感”的排序规则,所以上面的SELECT将工作。

我使用 unaccent module的 – 这是一个完全不同于你所链接的东西。

unaccent is a text search dictionary that removes accents (diacritic
signs) from lexemes.

每个数据库安装一次:

CREATE EXTENSION unaccent;

如果你得到一个错误,如:

ERROR: could not open extension control file
“/usr/share/postgresql/9.x/extension/unaccent.control”: No such file
or directory

在数据库服务器上安装contrib包,就像在这个相关的答案中所说的:

> Error when creating unaccent extension on PostgreSQL

除此之外,它还提供了可以与您的示例(其中LIKE似乎不需要)一起使用的函数unaccent()。

SELECT *
FROM   users
WHERE  unaccent(name) = unaccent('Jo?o');

指数

要为这种查询使用索引,请创建一个index on the expression.但是,Postgres仅接受索引的IMMUTABLE函数。如果一个函数可以为同一个输入返回不同的结果,那么索引可能会无声地断开。

unaccent()只有STABLE不是IMMUTABLE

不幸的是,unaccent()只是STABLE,而不是IMMUTABLE。根据this thread on pgsql-bugs,这是由于三个原因:

>它取决于字典的行为。
>没有到这个字典的硬接线连接。
>因此它也取决于当前的search_path,它可以很容易改变。

Some tutorials在web上指示只是将函数的易变性改为IMMUTABLE。这种强力方法在某些情况下可能会中断。

其他人建议一个simple IMMUTABLE wrapper function – 像我自己在过去。

有一个持续的争论是否使明确声明使用的字典的variant with two parameters IMMUTABLE。阅读here或here。

另一个选择是这个模块与一个IMMUTABLE unaccent() function by Musicbrainz,提供Github。没有自己测试。我想我已经提出了一个更好的主意:

最好的

我提出一种方法,至少与其他解决方案一样有效,但更安全:
创建一个包含两个参数形式的包装器函数,并为函数和字典“硬连线”模式:

CREATE OR REPLACE FUNCTION f_unaccent(text)
  RETURNS text AS
$func$
SELECT public.unaccent('public.unaccent',$1)  -- schema-qualify function and dictionary
$func$  LANGUAGE sql IMMUTABLE;

public是您安装扩展的模式(public是默认值)。

更新02.2016:以前,我添加了SET search_path = public,pg_temp到函数 – 直到我发现字典也可以是模式限定的,which is currently not documented.这个版本有点更短,是我在pg上的测试的两倍9.5并允许 function inlining。

你可以在这个IMMUTABLE函数上建立一个expression index:

CREATE INDEX users_unaccent_name_idx ON users(f_unaccent(name));

调整您的查询以使用索引:

SELECT *
FROM   users
WHERE  f_unaccent(name) = f_unaccent('Jo?o');

你不需要在正确的表达式中的函数。你可以直接提供不重要的字符串,如“Joao”。

连字

在Postgres 9.5或更高版本中,我们需要手动(如果我们需要)展开连字,如“?”或“?”,因为unaccent()总是替换一个字母:

SELECT unaccent('? ? ? ? ?');

unaccent
----------
E A e a S

你会爱上this update to unaccent在Postgres 9.6:

Extend contrib/unaccent‘s standard unaccent.rules file to handle all
diacritics known to Unicode,and expand ligatures correctly (Thomas
Munro,Léonard Benedetti)

大胆强调我。现在我们得到:

SELECT unaccent('? ? ? ? ?');

unaccent
----------
OE AE oe ae ss

模式匹配

对于具有任意模式的LIKE或ILIKE,将其与PostgreSQL 9.1或更高版本中的模块pg_tgrm组合。创建GIN(优选)或GIST表达式索引。 GIN的示例:

CREATE INDEX users_unaccent_name_trgm_idx ON users
USING gin (f_unaccent(name) gin_trgm_ops);

GIN and GIST indexes are more expensive to maintain.此索引可用于以下查询:

SELECT *
FROM   users
WHERE  f_unaccent(name) LIKE ('%' || f_unaccent('Jo?o') || '%');

对于刚刚左边锚定的模式有更简单的解决方案。更多关于模式匹配和性能:

> Pattern matching with LIKE,SIMILAR TO or regular expressions in PostgreSQL

pg_tgrm还提供了useful operators for “similarity” % and “distance” <->

Trigram索引也支持简单的正则表达式??。和与ILIKE的不区分大小写模式匹配:

> PostgreSQL accent + case insensitive search

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读