熟悉数据库的朋友,对存储过程或自定义函数返回结果集的问题可能会比较关心。我们在存储过程或自定义函数做了各种处理后,可能最终要返回一个结果集,在程序的客户端接收。
![93ae52f2d898e36e099823438a2384c6.png](https://i-blog.csdnimg.cn/blog_migrate/a550c61fb958395135904b7da7ecf9fe.jpeg)
比如在SQLServer中,使用存储过程返回结果集就非常简单,最后一条被执行的select语句会自动返回结果集。在SQLServer的自定义函数中,要返回结果集稍微复杂,需要定义返回的表结构才能返回。
PostgreSQL的存储过程是不支持返回值的,但函数却可以。下面我们就一起看看使用函数返回结果集的几种方式,并从中选出最适合我们要求的方式。
通过声明setof 表/视图 返回类型
这种方式是基于已经存在的表或者视图返回数据。请看下例:
create or replace function myfun() return setof t1 as $body$ declare result record; begin for result in select * from t1 loop return next result; end loop; return; end; $body$ language 'plpgsql';
![08e61a02dcaaa196876333a7936c702d.png](https://i-blog.csdnimg.cn/blog_migrate/739f966203b2ec40382534fc4375b29e.jpeg)
如果不使用循环调用的方式,可直接返回,脚本参考如下:
create or replace function myfun() returns setof t1 as $$begin return query select * from t1;end;$$language plpgsql;
![a160327768d49e2e7d06f7824d0021db.png](https://i-blog.csdnimg.cn/blog_migrate/84e614fbaa7c03336779c89285835f98.jpeg)
这两种种方式的缺点都是很明显的,我们要返回的,必须是基于已经存在的表或者视图的固定结构,很多情况下是很难满足我们的要求的。
通过声明setof record 返回类型
这种方式通过声明返回类型为record,可以在传出参数中定义传出字段,通过循环获取返回结果集。请参考以下实例:
create or replace function myfun(out f1 text,out f2 text) returns setof record as$$declare myrec record;begin for myrec in select f1,f2 from t1 loop f1:=myrec.field1; f2:=myrec.field2; return next; end loop; end;$$language plpgsql;
![f528876fb52fe65bbf1f6bbbdfe99eab.png](https://i-blog.csdnimg.cn/blog_migrate/62ded6c058d7e8b4e9785189d1b56ee9.jpeg)
这种方式一定程度上解决了动态字段的问题,但还是不够灵活,要求我们要预先定义传出参数,也是不太符合我们要求的。
通过声明 refcursor 返回类型
这是一种返回游标的方式,能够从根本上解决动态字段的问题。参考如下脚本:
create or replace function myfun() returns refcursor as $body$ declare result refcursor; begin open result for select * from t1,t2; return result; end; $body$ language 'plpgsql';
![48e71124d29d02f37c8f17c6f36b1a25.png](https://i-blog.csdnimg.cn/blog_migrate/fcb2c2eddb28d085b85588c437acd046.jpeg)
使用refcursor方式,能够自由返回查询的结果集,而我们并不需要关注固定的或视图结构,也不需要定义返回参数列表,查询的是什么就返回什么,这正是我们想要的方式!
![45f609448451091b21a269d06c99ea23.png](https://i-blog.csdnimg.cn/blog_migrate/cd0760b6aa31b5f8af821396b9067877.jpeg)
希望对您有所帮助!