perform 是 postgresql 中 function 内调用有返回值函数且忽略结果的唯一合法方式;select 会报错,call 仅适用于 procedure,perform 丢弃结果但执行副作用,不可获取返回值。

PERFORM 是唯一合法的无返回调用方式
在 PostgreSQL 的 FUNCTION(不是 PROCEDURE)中,如果目标函数有返回值但你不想接收它,必须用 PERFORM,不能写 SELECT my_func(...) 或 CALL my_func(...)。后者要么语法报错,要么语义错误——CALL 只能用于 PROCEDURE,而 SELECT 会试图把返回值当作查询结果集返回,触发“function cannot return a set”或“query has no destination”错误。
-
PERFORM本质是把SELECT的执行逻辑复用,但强制丢弃结果;内部仍会执行函数体、触发副作用(如 INSERT/UPDATE/RAISE NOTICE) - 调用后可通过
FOUND判断是否返回了至少一行(对返回SETOF的函数有效),但无法拿到具体值 - 若被调用函数声明为
RETURNS VOID,PERFORM和CALL都可用,但混用易引发维护混淆——建议统一用PERFORM保持函数上下文一致性
调用带参数的函数时,参数类型必须严格匹配重载签名
PostgreSQL 按「函数名 + 参数类型 OID 列表」区分重载版本。PERFORM calculate_sum(3, 5) 调用的是 calculate_sum(integer, integer),但如果定义过 calculate_sum(int4, int4) 或 calculate_sum(numeric, numeric),实际绑定可能出乎意料。常见陷阱:
- 误写
PERFORM calculate_sum(3::text, 5)→ 类型不匹配,直接报function calculate_sum(text, integer) does not exist - 默认参数未显式写出:若函数定义为
my_func(a int, b int = 10),则PERFORM my_func(1)合法,但PERFORM my_func(1, DEFAULT)语法错误(PL/pgSQL 不支持DEFAULT关键字占位) - 检查当前所有重载:在 psql 中运行
\df+ calculate_sum,确认 OID 和参数类型
PERFORM 后无法直接获取返回值,需改用 SELECT INTO
想拿返回值,就不能用 PERFORM。例如要捕获 calculate_sum() 的整数结果:
DECLARE sum_result INTEGER; BEGIN -- 错误:PERFORM 丢弃结果 PERFORM calculate_sum(2, 3); <p>-- 正确:用 SELECT INTO 接收单行单列 SELECT calculate_sum(2, 3) INTO sum_result;</p><p>-- 更安全:加 STRICT 防多行或空行 SELECT calculate_sum(2, 3) INTO STRICT sum_result; END;</p>
-
INTO要求函数返回恰好一行一列,否则抛NO_DATA_FOUND或TOO_MANY_ROWS - 若函数返回表(
RETURNS TABLE(...)),必须用CREATE TEMP TABLE AS SELECT ...或循环FOR rec IN SELECT ... LOOP处理 -
PERFORM和SELECT INTO性能无差异,区别纯属语义:要不要值
事务行为和异常传播容易被忽略
PERFORM 调用的函数内若发生异常(如除零、唯一约束冲突),默认会中止整个外层函数执行,并回滚已做修改——除非在外层或被调用函数中显式用 EXCEPTION 捕获。这点和普通 SQL 执行一致,但新手常以为 PERFORM 是“静默调用”就等于“错误被吞掉”。
- 被调用函数里
RAISE EXCEPTION会透传,外层不捕获就崩 - 若被调用函数含
COMMIT或ROLLBACK(仅PROCEDURE允许),在FUNCTION中用PERFORM调用会直接报错:cannot commit inside a function - 调试时加
RAISE NOTICE比依赖返回值更直观,因为PERFORM本身不输出任何东西










