Postgresql

INDEX 中使用的 CONCAT 導致錯誤:索引表達式中的函式必須標記為 IMMUTABLE

  • July 26, 2016

我面臨以下錯誤:

ERROR:  functions in index expression must be marked IMMUTABLE

嘗試創建這樣的索引時:

CREATE INDEX full_phone_number ON orders_clientphone (concat(area_code, phone));

另一方面,當使用替代語法進行連接時:

CREATE INDEX full_phone_number ON orders_clientphone ((area_code || phone));

Postgres 對此非常滿意。

兩列都定義為character varying(256)

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

手冊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

內部使用的函式取決於操作數的實際數據類型。運算符的定義包括 Postgres 中操作數的數據類型。所有的功能都不同,也不同於text_concat上面。||當其中一個運算符為 時,它也很穩定anynonarray。窗簾後面的事情並不是那麼瑣碎。

character varying(256)(像任何varchar變體一樣)是二進制強制的,text因此函式類型解析預設為text.

引用自:https://dba.stackexchange.com/questions/144839