问题描述
我有以下带有 INOUT 参数的 Postgres 存储过程。
PROCEDURE inner_proc(IN pid INT,INOUT pmsg TEXT);
我可以从匿名块成功调用这个过程。
do
$$
declare
v_id int := 4;
v_msg text;
begin
call inner_proc(pid => v_id,pmsg => v_msg);
raise notice '%',v_msg;
end;
$$
language plpgsql;
上面的匿名块按预期打印 'Success'
。
但是当我在另一个过程中调用这个过程时,它失败了。
PROCEDURE outer_proc()
as
$$
declare
v_id int := 4;
v_msg character varying(1000);
begin
call inner_proc(pid => v_id,v_msg;
end;
$$
language plpgsql;
call outer_proc();
ERROR: procedure parameter "pmsg" is an output parameter but corresponding argument is not writable
有人可以帮忙解决这个问题吗?
解决方法
原因是v_msg
中的outer_proc
是character varying
类型,而pmsg
的参数inner_proc
是text
类型。
因此,当您使用 inner_proc
调用 v_msg
时,PostgreSQL 会执行类型转换。在 character varying
→ text
的情况下,这只是一种“类型强制”,因为这些类型的内部表示是相同的,但也可能是真正的转换,如 integer
→ bigint
。
现在这适用于 IN
方向,但现在 inner_proc
的参数不再是一个普通的变量,而是一个包含参数的表达式,就像你传递了 {{1 }}。当然,不可能将输出值分配给这样的表达式,因此会出错。
有人可能会争辩说结果可以简单地强制转换回 v_msg || 'tail'
,但是 a) 没有人为这种特殊情况实施额外的处理,并且 b) 不能保证总是有一个强制转换反方向。