PostgreSQL是否支持;“不区分重音”;整理?

PostgreSQL是否支持;“不区分重音”;整理?,sql,postgresql,localization,indexing,pattern-matching,Sql,Postgresql,Localization,Indexing,Pattern Matching,在Microsoft SQL Server中,可以指定“不区分重音”的排序规则(对于数据库、表或列),这意味着可以对类似 SELECT * FROM users WHERE name LIKE 'João' 查找具有Joao名称的行 我知道可以使用contrib函数从PostgreSQL中的字符串中去除重音,但我想知道PostgreSQL是否支持这些“不区分重音”的排序规则,这样上面的SELECT就可以工作了。我很确定PostgreSQL依赖于底层操作系统进行排序。它确实支持,并且。不过,我不

在Microsoft SQL Server中,可以指定“不区分重音”的排序规则(对于数据库、表或列),这意味着可以对类似

SELECT * FROM users WHERE name LIKE 'João'
查找具有
Joao
名称的行


我知道可以使用contrib函数从PostgreSQL中的字符串中去除重音,但我想知道PostgreSQL是否支持这些“不区分重音”的排序规则,这样上面的
SELECT
就可以工作了。

我很确定PostgreSQL依赖于底层操作系统进行排序。它确实支持,并且。不过,我不确定你需要做多少工作。(可能会有很多。)

使用,这与您正在链接的内容完全不同

uncent是一个文本搜索词典,它删除重音(变音) 符号)来自词汇表

使用以下各项为每个数据库安装一次:

CREATE EXTENSION unaccent;
如果出现如下错误:

指数 若要为此类查询使用索引,请创建一个然而,Postgres只接受索引的
不可变
函数。如果函数可以为同一输入返回不同的结果,则索引可能会自动中断

uncent()
稳定
不可变
不幸的是,
uncent()。据认为,这是由于三个原因:

  • 这取决于词典的行为
  • 此词典没有硬连线连接
  • 因此,它还取决于当前的
    搜索路径
    ,该路径很容易更改
  • 在web上,只需将函数volatile更改为
    不可变
    。这种蛮力方法在某些情况下会失效

    其他人则提出了一个新的建议(就像我过去做的那样)

    是否使显式声明所用词典的
    不可变
    ,一直存在争议。读或读

    另一个替代方案是Github上提供的带有的模块。我自己还没有测试过。我想我想出了一个更好的主意:

    现在最好 这种方法与其他解决方案相比,效率更高,更安全
    创建一个
    不可变的
    SQL包装函数,使用硬连线的模式限定函数和字典执行双参数表单

    因为嵌套一个非不可变函数会禁用函数内联,所以它也基于C函数的一个副本,(伪)声明
    不可变
    。它的唯一用途是在SQL函数包装器中使用。不打算单独使用

    复杂度是必需的,因为在C函数的声明中无法硬连接字典。(需要破解C代码本身。)SQL包装器函数可以做到这一点,并允许函数内联和表达式索引

    CREATE OR REPLACE FUNCTION public.immutable_unaccent(regdictionary, text)
      RETURNS text LANGUAGE c IMMUTABLE PARALLEL SAFE STRICT AS
    '$libdir/unaccent', 'unaccent_dict';
    
    CREATE OR REPLACE FUNCTION public.f_unaccent(text)
      RETURNS text LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS
    $func$
    SELECT public.immutable_unaccent(regdictionary 'public.unaccent', $1)
    $func$;
    
    从Postgres 9.5或更早版本的两个功能中删除并行安全设置

    public
    是安装扩展的架构(
    public
    是默认设置)

    显式类型声明(
    regdictionary
    )防止恶意用户使用函数的重载变体进行假设攻击

    以前,我提倡使用基于uncent模块附带的
    STABLE
    函数
    uncent()
    的包装函数。那是残疾。这个版本的执行速度是我之前使用的简单包装函数的十倍。
    这已经是第一个版本的两倍,第一个版本在函数中添加了
    setsearch\u path=public,pg\u temp
    ,直到我发现字典也可以符合模式

    如果您缺乏创建C函数所需的特权,那么您就回到了第二个最佳实现:围绕模块提供的
    稳定的
    函数的
    不可变的
    函数包装器:

    CREATE OR REPLACE FUNCTION public.f_unaccent(text)
      RETURNS text AS
    $func$
    SELECT public.unaccent('public.unaccent', $1)  -- schema-qualify function and dictionary
    $func$  LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT;
    
    最后,使用表达式索引来快速查询:

    记得在对函数或字典进行任何更改后,重新创建涉及此函数的索引,例如不会重新创建索引的就地主要版本升级。最近的主要发行版都有
    未登录
    模块的更新

    调整查询以匹配索引(以便查询规划器将使用它):

    您不需要正确表达式中的函数。在那里,您还可以直接提供非注释字符串,如
    'Joao'

    使用时,更快的函数不能转换为更快的查询。它根据预先计算的值进行操作,并且已经非常快了。但是索引维护和查询不使用索引的好处

    Postgres 10.3/9.6.8等加强了客户端程序的安全性。在任何索引中使用时,都需要对函数和字典名进行模式限定。见:

    结扎 在Postgres9.5或以上的中,像“Œ”或“ß”这样的连字必须手动展开(如果需要的话),因为
    uncent()
    总是替换一个字母:

    你会爱上博士后9.6

    扩展
    contrib/uncent
    的标准
    uncent.rules
    文件以处理所有 Unicode已知的变音符号,并正确扩展连字 蒙罗,莱昂纳德·贝内代蒂)

    我的。现在我们得到:

    SELECT unaccent('Œ Æ œ æ ß');
    
    unaccent
    ----------
    OE AE oe ae ss
    
    模式匹配 对于具有任意模式的
    ILIKE类
    ,请将其与PostgreSQL 9.1或更高版本中的模块结合使用。创建一个trigram GIN(通常更好)或GIST表达式索引。杜松子酒的例子:

    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索引的维护成本高于普通btree:

    T
    SELECT * FROM users
    WHERE  f_unaccent(name) = f_unaccent('João');
    
    SELECT unaccent('Œ Æ œ æ ß');
    
    unaccent
    ----------
    E A e a S
    
    SELECT unaccent('Œ Æ œ æ ß');
    
    unaccent
    ----------
    OE AE oe ae ss
    
    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') || '%');
    
    CREATE EXTENSION unaccent;
    
    CREATE TEXT SEARCH CONFIGURATION mydict ( COPY = simple );
    ALTER TEXT SEARCH CONFIGURATION mydict
      ALTER MAPPING FOR hword, hword_part, word
      WITH unaccent, simple;
    
    -- Just some sample data...
    CREATE TABLE myTable ( myCol )
      AS VALUES ('fóó bar baz'),('qux quz');
    
    -- No index required, but feel free to create one
    CREATE INDEX ON myTable
      USING GIST (to_tsvector('mydict', myCol));
    
    SELECT *
    FROM myTable
    WHERE to_tsvector('mydict', myCol) @@ 'foo & bar'
    
        mycol    
    -------------
     fóó bar baz
    (1 row)