前言
Sybase存储过程支持直接返回多个结果集,而PostgreSQL默认不支持这种行为。PostgreSQL可以通过在函数参数中定义多个游标,通过游标间接返回多个数据集。但这种方法会导致存储过程参数变化,并且如果游标很多,也会导致代码臃肿,降低开发效率。本文介绍一种新的方法,可以保持存储过程的参数不变,同时实现多结果集的返回,从而实现无缝迁移。
现有方案
以下是Sybase原存储过程,返回两个结果集:
Create Procedure proc2 AS
BEGIN
select * from t1;
select * from t2;
END
Sybase中过以下SQL调用存储过程:
exec proc2
迁移时,现有方法需要定义返回两个游标参数的PostgreSQL存储函数:
Create Or Replace Procedure proc2( INOUT p1 refcursor, INOUT p2 refcursor )
LANGUAGE PlPgSQL
AS $$
BEGIN
open p1 for select * from t1;
open p2 for select * from t2;
END;$$;
PostgreSQL中可以通过以下SQL调用存储过程:
DO $$
Declare
p1 refcursor;
p2 refcursor;
BEGIN
CALL proc2( p1, p2);
END; $$
从上面代码可以看出,调用方式不一致了,PostgreSQL需要定义并传入更多的参数。下面介绍一种新方法,可以实现多结果集存储函数的无缝迁移。
新方案
为了在PostgreSQL中实现类似Sybase的多结果集返回,同时保持存储过程的参数不变,我们可以通过在存储过程内部定义游标名称,并在调用存储过程后通过游标名称获取数据。新的PostgreSQL代码如下:
Create Or Replace Procedure proc2( )
LANGUAGE PlPgSQL
AS $$
Declare
p1 refcursor :='p1';
p2 refcursor :='p2';
BEGIN
open p1 for select * from t1;
open p2 for select * from t2;
END;$$;
然后在PostgreSQL客户端通过以下方式调用存储过程:
CALL proc2();
FETCH ALL FROM p1;
FETCH ALL FROM p2;
通过对比可发现,新方法的调用方式与原Sybase是一致的,代码量也比原有方式要少,不用定义一堆的游标变量。
真实案例
CP8项目组有一个存储过程,返回170多个结果集。转换为PostgreSQL代码后,有170多个游标参数,这超出了PostgreSQL最大的100个参数的限制,导致运行失败。
:无缝迁移Sybase多结果集返回的存储过程/1572416507.png)
后来按上述新方案更改后,成功编译运行。调用简化为
CALL proc_xxxx( ‘aaa’, ‘ppp’, ‘jjj’ )
简单明了,且参数与原Sybase一致。
总结
在将Sybase存储过程迁移到PostgreSQL时,通过在存储过程内部定义游标名称,可以实现多结果集的返回,同时保持存储过程的参数不变。这种方式不仅减少了迁移成本,还确保了与现有应用程序的兼容性。