INDEX 中使用的 CONCAT 导致错误:索引表达式中的函数必须标记为 IMMUTABLE

and*_*abs 9 postgresql index datatypes functions postgresql-9.4

我面临以下错误:

ERROR:  functions in index expression must be marked IMMUTABLE
Run Code Online (Sandbox Code Playgroud)

尝试创建这样的索引时:

CREATE INDEX full_phone_number ON orders_clientphone (concat(area_code, phone));
Run Code Online (Sandbox Code Playgroud)

另一方面,当使用替代语法进行连接时:

CREATE INDEX full_phone_number ON orders_clientphone ((area_code || phone));
Run Code Online (Sandbox Code Playgroud)

Postgres 对此非常满意。
两列都定义为character varying(256)

Erw*_*ter 9

Postgres的决定因素是函数concat()的定义稳定没有一成不变的系统目录pg_proc

SELECT proname, provolatile, proargtypes, proargtypes[0]::regtype AS argtype, prosrc
FROM pg_proc
WHERE proname = 'concat';

proname | provolatile | proargtypes| argtype | prosrc
--------+-------------+------------+---------+-----------
concat  | s           | 2276       | "any"   | text_concat
Run Code Online (Sandbox Code Playgroud)

手册pg_proc.provolatile

provolatile告诉函数的结果是仅取决于其输入参数,还是受外部因素的影响。它适用i于“不可变”函数,对于相同的输入,它总是提供相同的结果。它s用于“稳定”功能,其结果(对于固定输入)在扫描内不会改变。

我还添加了函数 ( "any")的参数类型以连接到 @dezso 和 @jjanes 的答案,这提供了使此函数稳定的决定背后的基本原理。以及内部函数的名称 ( text_concat)。

这是一个相关的问题,用于说明为什么索引表达式的不变性是必要条件:

至于使用运算符||

    SELECT o.oprname, o.oprleft::regtype, o.oprright::regtype, o.oprcode, p.provolatile
    FROM   pg_operator o
    JOIN   pg_proc     p ON p.oid = o.oprcode
    WHERE  oprname = '||';


 oprname |   oprleft   |  oprright   |     oprcode     | provolatile
---------+-------------+-------------+-----------------+-------------
 ||      | anyarray    | anyelement  | array_append    | i
 ||      | anyelement  | anyarray    | array_prepend   | i
 ||      | anyarray    | anyarray    | array_cat       | i
 ||      | text        | text        | textcat         | i
 ||      | bit varying | bit varying | bitcat          | i
 ||      | bytea       | bytea       | byteacat        | i
 ||      | text        | anynonarray | textanycat      | s
 ||      | anynonarray | text        | anytextcat      | s
 ||      | tsvector    | tsvector    | tsvector_concat | i
 ||      | tsquery     | tsquery     | tsquery_or      | i
 ||      | jsonb       | jsonb       | jsonb_concat    | i
Run Code Online (Sandbox Code Playgroud)

内部使用的函数取决于操作数的实际数据类型。运算符的定义包括 Postgres 中操作数的数据类型。所有的功能都不同,也与text_concat上面不同。||当其中一个运算符为 时,也同样稳定anynonarray。幕后的事情并不是那么简单。

character varying(256)(像任何varchar变体一样)是二进制强制的text因此函数类型解析默认为text.

  • 那么,如果需要对文本串联的结果建立索引,该如何解决呢? (2认同)