PostgreSQL中三类函数是否属于Immutable函数的判定咨询
先明确PostgreSQL中Immutable函数的核心规则:
IMMUTABLE表示函数无法修改数据库,且给定相同参数值时始终返回相同结果;即函数不执行数据库查询,也不使用参数列表中未直接提供的信息。若指定该选项,所有参数均为常量的函数调用可直接替换为函数值。
针对你提出的三类函数,逐一分析:
1. 包含raise notice的函数
这类函数不能标记为Immutable。
虽然该函数的返回值满足“相同输入返回相同结果”的要求,但RAISE NOTICE会产生输出到客户端的副作用。PostgreSQL的优化器会对Immutable函数进行缓存或提前计算(比如将常量参数的调用直接替换为结果),这会导致RAISE NOTICE的输出行为不符合预期——比如多次调用可能只输出一次通知,甚至完全不输出。这类函数适合标记为STABLE或VOLATILE。
示例函数:
CREATE OR REPLACE FUNCTION text_equals(text, text) RETURNS boolean AS $$ BEGIN RAISE NOTICE 'Comparing two texts'; RETURN $1 = $2; END; $$ LANGUAGE plpgsql;
2. 调用其他Immutable函数的函数
这类函数可以标记为Immutable,但需要满足前提条件:
- 函数的逻辑完全依赖输入参数,不依赖任何外部状态(比如会话变量、数据库数据);
- 仅调用Immutable函数,没有其他副作用(比如修改数据、输出通知);
- 自身逻辑不会引入不确定性。
比如下面的函数就可以标记为Immutable:
CREATE OR REPLACE FUNCTION text_upper_equals(text, text) RETURNS boolean AS $$ BEGIN RETURN upper($1) = upper($2); END; $$ LANGUAGE plpgsql IMMUTABLE;
因为upper是Immutable函数,该函数仅依赖输入参数,无副作用,相同输入必然返回相同结果。
3. 返回current_user的函数
这类函数不属于Immutable函数。current_user是与会话上下文相关的变量,即使没有输入参数(即“输入相同”),不同用户或不同会话调用时结果也会不同,完全违反Immutable函数“相同输入返回相同结果”的核心要求。
关于SECURITY DEFINER的补充说明:
当函数带有SECURITY DEFINER属性时,函数会以函数创建者的身份执行,因此current_user返回的是函数创建者的用户名,而非调用该函数的用户。
示例函数:
CREATE OR REPLACE FUNCTION fun() RETURNS TEXT AS $$ DECLARE current_user_text TEXT; BEGIN current_user_text := 'Current user is ' || current_user; RETURN current_user_text; END; $$ LANGUAGE plpgsql SECURITY DEFINER;
内容的提问来源于stack exchange,提问作者Ayush Vatsa

