使用PLPGSQL在循环存储过程中调用另一个存储过程失败
问题分析
报错的核心原因:
quality_save存储过程定义了INOUT response参数,调用时必须传入一个可写变量接收它的输出值,但你在auto_save里调用时未传递该参数,PostgreSQL因此判定对应参数不可写并报错。auto_save内部重复声明了response变量(参数已包含该变量,内部再次declare属于冗余操作),会屏蔽外部的INOUT参数,进一步引发逻辑混乱。
修复方案
- 删除
auto_save内部重复声明的response varchar(100);,保留参数中的INOUT response即可。 - 调用
quality_save时必须传入response参数,让它能将返回值写入这个变量。如果需要遇到错误就终止循环,或者收集所有错误信息,可以按需调整逻辑。
修改后的代码
CREATE OR REPLACE PROCEDURE quality_save(p_1 character varying, p_2 character varying, p_3 character varying DEFAULT NULL::character varying, INOUT response character varying DEFAULT '1'::character varying) LANGUAGE plpgsql AS $procedure$ declare begin raise notice '_Insert start'; insert into table_A(brand, model, year) values(p_1, p_2, p_3); raise notice 'insert-end'; exception when sqlstate '23505' then response := 'Duplicate Record'; --when others then -- response := '-1'; end; $procedure$; -- 修复后的auto_save存储过程 CREATE OR REPLACE PROCEDURE auto_save(INOUT response character varying DEFAULT '1'::character varying) LANGUAGE plpgsql AS $procedure$ declare f record; begin for f in select p_1,p_2,p_3 from table_dump loop -- 调用时传入response参数,接收quality_save的返回值 call public.quality_save( p_1 => f.p_1, p_2 => f.p_2, p_3 => f.p_3, response => response ); -- 可选:如果遇到错误就停止循环,取消下面注释即可 -- if response != '1' then -- exit; -- end if; end loop; end; $procedure$;
额外优化说明
- 原
quality_save中的if 1=1属于冗余判断,直接执行插入逻辑即可。 - 用
response := 'xxx'赋值比select 'xxx' into response更简洁高效。 - 如果需要收集循环中所有的执行结果(而非仅保留最后一个),可以定义数组变量来存储每次的response值,最后合并为输出内容。
内容的提问来源于stack exchange,提问作者SQLLER
相关产品推荐
相关产品推荐

