为何调用PostgreSQL存储过程时OUT参数不可留空?
PL/pgSQL OUT参数的CALL调用规则解析
首先看定义的存储过程及调用示例:
CREATE OR REPLACE PROCEDURE test1(OUT i int) LANGUAGE plpgsql AS $$ BEGIN i:=10; END; $$; CALL test1(1); -- 可正常执行,返回10,传入的数值1被忽略 CALL test1(); -- 执行失败,报错:procedure test1() does not exist Hint: No procedure matches the given name and argument types. You might need to add explicit type casts. Position: 6
核心问题解析:
1. 为什么OUT参数的传入初始值会被忽略?
OUT参数的设计定位就是仅用于输出结果,它的生命周期是:存储过程启动时,会自动将OUT参数初始化为对应数据类型的默认值(比如int类型默认是NULL),之后过程体内的赋值操作会覆盖这个初始值。哪怕你调用时传入了字面量或者变量的初始值,都会被这个初始化步骤覆盖,所以传入的值自然不会生效。
2. 为什么OUT/INOUT参数在CALL时必须对应变量(或至少占参数位置)?
- 存储过程签名的严格匹配:PostgreSQL会根据参数的数量、类型和模式(IN/OUT/INOUT)来匹配存储过程签名。
test1(OUT i int)的签名要求有一个int类型的参数位置,哪怕是OUT模式,你也必须在调用时为这个位置提供一个值(变量或字面量),否则数据库会认为你要调用的是无参数的test1(),而这个签名的存储过程不存在,因此报错。 - 输出结果需要可写入载体:规范要求传变量的原因是,OUT参数最终要把计算结果返回给调用者,字面量是不可修改的常量,无法承载输出结果。虽然传字面量能绕过语法检查,但没有实际意义——你没法从字面量里拿到输出值。而变量是可写入的,调用者可以通过变量获取存储过程输出的结果,比如正确的用法应该是:
DECLARE res int; CALL test1(res); SELECT res; -- 得到输出结果10
内容的提问来源于stack exchange,提问作者Akthar
相关产品推荐
相关产品推荐

