PostgreSQL 14: 存储过程支持 OUT 参数

John Doe 七月 24, 2025

Oracle 中的存储过程可以带输出参数,你需要将它们迁移到 PostgreSQL 吗?

沙滩上漫步的大象

特性提交日志

支持存储过程中的 OUT 参数。

与函数不同,存储过程的 OUT 参数是其签名的一部分。因此,它们必须在pg_proc.proargtypes中列出,并且在ALTER PROCEDUREDROP 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