PostgreSQL支持“不区分变音”sorting规则吗?

在Microsoft SQL Server中,可以指定“不区分重音”的sorting规则(对于数据库,表或列),这意味着可能会执行类似查询

SELECT * FROM users WHERE name LIKE 'João' 

find一个与Joao名字。

我知道可以使用unaccent_string contrib函数从PostgreSQL中的string中删除重音,但是我想知道PostgreSQL是否支持这些“不区分变音”的sorting规则,所以上面的SELECT可以工作。

使用unaccent模块 – 这是完全不同于你链接到。

unaccent是一个文本search词典,可以从词位中删除重音符号(变音符号)。

每个数据库安装一次:

 CREATE EXTENSION unaccent; 

如果您得到如下错误:

错误:无法打开扩展控制文件“/usr/share/postgresql/9.x/extension/unaccent.control”:没有这样的文件或目录

在你的数据库服务器上安装contrib软件包,就像这个相关的答案一样:

  • 在PostgreSQL上创build不完整的扩展时出错

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

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

指数

要为这种查询使用索引,请在expression式上创build一个索引 。 但是 ,Postgres只接受索引的IMMUTABLE函数。 如果一个函数可以为同一个input返回一个不同的结果,索引可以静静地中断。

IMMUTABLE unaccent()只有STABLE不可IMMUTABLE

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

  1. 这取决于字典的行为。
  2. 这本字典没有硬连线。
  3. 因此它也取决于当前的search_path ,它可以很容易地改变。

网上的一些教程指示将functionIMMUTABLE性改为IMMUTABLE 。 这种powershell方法可以在某些条件下破坏。

其他人则提出了一个简单的IMMUTABLE包装函数 (就像我过去一样)。

是否使用两个参数 IMMUTABLE来明确声明使用的字典是一个持续的争论。 阅读这里或这里 。

另一个替代scheme是在Github上提供的带有Musicbrainz的IMMUTABLE unaccent unaccent()函数的模块。 没有自己testing过。 我想我已经想出了一个更好的主意

现在最好的

我提出的方法至less与其他解决scheme一样高效,但更安全 :使用双参数forms创build包装器函数,并为函数和字典“架线”模式:

 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到函数中,直到我发现字典也可以是模式限定的,而且目前还没有logging 。 这个版本稍微短一点,比我在第9.5页的testing中快了一倍以上,并允许函数内联 。

您可以在此IMMUTABLE函数上使用expression式索引 。 喜欢:

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

调整您的查询以匹配索引(所以查询计划者可以使用它):

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

您不必严格需要正确expression式中的函数。 你可以直接提供像'Joao'这样'Joao'重叠的string。

连字

在Postgres9.5 或更老的版本中 ,必须手动扩展(如果需要的话),因为unaccent()总是用一个字母代替:

 SELECT unaccent('Œ Æ œ æ ß'); unaccent ---------- EA ea S 

你会喜欢这个更新在Postgres 9.6中不起作用:

扩展contrib/unaccent的标准unaccent.rules文件来处理Unicode已知的所有变音符号,并正确地扩展连字 (Thomas Munro,LéonardBenedetti)

大胆重视我的。 现在我们得到:

 SELECT unaccent('Œ Æ œ æ ß'); unaccent ---------- OE AE oe ae ss 

模式匹配

对于具有任意模式的LIKEILIKE ,请将其与PostgreSQL 9.1或更高版本中的模块pg_trgm结合使用。 创build一个三元组GIN(通常更可取)或GISTexpression式索引。 GIN示例:

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

可以用于像这样的查询:

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

GIN和GIST索引比普通树更昂贵:

  • GiST和GIN指数的区别

只有左锚模式有更简单的解决scheme。 关于模式匹配和性能的更多信息

  • 在PostgreSQL中与LIKE,SIMILAR TO或正则expression式匹配的模式

pg_trgm还为“相似性”( % )和“距离”( <-> )提供了有用的运算符 。

Trigram索引还支持〜et al的简单正则expression式。 和与ILIKE 不区分大小写的模式匹配:

  • PostgreSQL口音+不区分大小写的search

我很确定PostgreSQL依靠底层操作系统进行整理。 它支持创build新的sorting规则和自定义sorting规则 。 不过,我不确定可以为你做多less工作。 (可能相当多)