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上的这个线程 ,这是由于三个原因:
- 这取决于字典的行为。
- 这本字典没有硬连线。
- 因此它也取决于当前的
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
模式匹配
对于具有任意模式的LIKE
或ILIKE
,请将其与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工作。 (可能相当多)