Postgresql
INDEX 中使用的 CONCAT 導致錯誤:索引表達式中的函式必須標記為 IMMUTABLE
我面臨以下錯誤:
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
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
.