由 John Doe 七月 24, 2025
Oracle 中的存储过程可以带输出参数,你需要将它们迁移到 PostgreSQL 吗?
特性提交日志
支持存储过程中的 OUT 参数。
与函数不同,存储过程的 OUT 参数是其签名的一部分。因此,它们必须在pg_proc.proargtypes
中列出,并且在ALTER PROCEDURE
和DROP PROCEDURE
中提及。
讨论:https://www.postgresql.org/message-id/flat/2b8490fe-51af-e671-c504-47359dc453c5@2ndquadrant.com
示例
PostgreSQL 11 开始引入了存储过程,它们解决了在数据库中可跨多个事务复用逻辑的这一问题。
但存储过程始终无法返回数据。你可以调用它们,但不能从它们进行 SELECT 查询。因此,尽管你可以使用RAISE NOTICE
以某种方式返回数据,但如果不采取一些复杂的手段,就无法在常规查询中使用这些数据。
这种情况已经成为历史了。有了这次新提交的特性,我们现在可以从存储过程中返回数据了。
我们来看一个非常简单的示例:
create procedure test( IN elements INT4, OUT created int4[], OUT failed int4[] )
language plpgsql as $$
declare
i int4;
begin
for i in 1 .. elements loop
IF random() < 0.5 THEN
failed := failed || i;
ELSE
created := created || i;
END IF;
end loop;
end;
$$;
这个存储过程会遍历指定数量的元素,对于每个元素(范围在 1 到给定数字之间的整数),会根据随机结果判断该元素应放入 “created” 数组还是 “failed” 数组。
这个示例非常简单,完全没有实际用途,但能正常工作:
call test(15, '{}'::int4[], '{}'::int4[]);
created | failed
----------------------+--------------------
{1,2,4,6,8,11,14,15} | {3,5,7,9,10,12,13}
(1 row)
有一点需要注意:赋予 OUT 参数的值无关紧要,在执行存储过程之前,输出参数的值会被预设为 NULL。
call test(2, '{10,11}'::int4[], '{12,13}'::int4[]);
created | failed
---------+--------
{2} | {1}
(1 row)
这样一来,PostgreSQL 的存储过程就更加兼容 Oracle 了。非常不错的体验,感谢所有参与的社区人员。
参考
提交日志:https://git.postgresql.org/pg/commitdiff/2453ea142233ae57af452019c3b9a443dad1cdd0