pgsql function 系列之一:返回结果集
--------------------------------------------------------------------------------
我们在编写postgresql数据库的函数(或称为存储过程)时,时常会遇到需要返回一个结果集的情况,如何返回一个结果集,返回一个结果集有多少种方式,以及如何选择一个合适的方式返回结果集,这是一个需要仔细考虑的问题。本文仅简单的罗列出各种返回结果集的方式并试图分析他们的特点,而采用何种方式则留给大家自己去判断。 
阅读本文需要一定的postgresql数据库端编程知识,如果你缺乏这方面的知识,请先翻阅postgresql文档。 

----------------------------------------------------分割线------------------------------------------------------- 

第一种选择:声明setof 某表/某视图 返回类型 
这是postgresql官方推荐的返回结果集的形式,当你查阅postgresql官方文档的时候,你会看到的就是这种形式。如果采用这种形式,你的function代码看起来会像这样:CREATE OR REPLACE FUNCTION function1 () RETURNS setof table1 AS 
$body$ 
DECLARE 
result record; 
BEGIN 
for result in select * from table1 loop 
return next result; 
end loop; 
return; 
END; 
$body$ 
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER; 

这是使用pl/pgsql语言的风格,你甚至可以使用sql语言让代码看起来更简单: 

CREATE OR REPLACE FUNCTION function1 () RETURNS SETOF table1 AS 
$body$ 
SELECT * from table1; 
$body$ 
LANGUAGE 'sql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER; 

以下是分析: 
首先我们说优点,第一、这是官方推荐的;第二、当使用pl/pgsql语言的时候,我们可以在循环中加上判断语句,仅返回我们需要的行;第三、在jdbc调用中,我们可以像查询普通的表一样使用这个function,例如:"select * from function1()"。 
其次我们说缺点,第一、当使用pl/pgsql语言的时候,即使我们需要返回所有行,仍然要进行循环导致不必要的开销。当然你可以使用sql语言避免这个问题,但显然sql语言的控制能力太弱以至于我们无法使用它实现哪怕稍微复杂一点的逻辑。第二、返回的字段必须是在function定义时就确定了的,这意味着我们无法动态的返回我们想要返回的字段。 

------------------------------------------------继续分割线------------------------------------------------- 

第二种选择:声明setof record返回类型 
总的说起来这种方式和上一种没什么不同,它唯一的用处在于“一定程度上”解决了动态返回结果集字段的问题。之所以说“一定程度”是因为使用setof record返回类型将会导致极度恶心的jdbc端编码——你不得不在sql语句后面显式的说明所选字段的名称和类型,并且你会发现你无法使用jdbc call的方式调用function(关于jdbc call的部分在另外的篇幅描述)。具体的来说,如果你返回一个结果集字段按照:a bigint,b varchar,c timestamp排列,则你的jdbc端编码看起来会像这样: 

select * from function1() as (a bigint,b varchar,c timestamp); 

问题在于,如果你不知道function将要返回的字段类型是什么,则你根本无法在jdbc端调用该function!!! 

----------------------------------------------还是分割线------------------------------------------------- 

第三种选择:声明refcursor返回类型 
事情到这里将揭过新的一页,这里我们放弃使用setof ××× ,而使用一个全新的返回类型——refcursor(游标)。关于什么是游标本文不再累述,请自己翻阅相关文档,这里仅描述如何使用。 
首先,要使用游标,你的function编码看起来会像这样: 
CREATE OR REPLACE FUNCTION function1 () RETURNS refcursor AS 
$body$ 
DECLARE 
result refcursor; 
BEGIN 
open result for select * from table1,table2; --你可以任意选择你想要返回的表和字段 
return result; 
END; 
$body$ 
LANGUAGE 'plpgsql' VOLATILE CALLED ON NULL INPUT SECURITY INVOKER; 

你的jdbc端编码推荐使用call方式,看起来会像这样: 

Connection conn = ConnectionPool.getConn(); 
CallableStatement proc = conn.prepareCall("{ ? = call function1() }"); 
proc.execute(); 
ResultSet rs = (ResultSet) proc.getObject(1); 

如此我们就获得了一个结果集,并且该结果集所包含的字段可以是任意你想要的字段,并且jdbc端编码也很简洁。 

然而这种方式的缺点依然很明显:我们不能对要返回的结果集做进一步的筛选(参考第一种选择的优点二)。 
----------------------------------------------最后分割线------------------------------------------------ 

总的来说,上述三种方法各有特点,我们在实际应用中应该秉着“合适的就是最好的”的原则来看待问题。

postgresql 函数返回结果集(zz)的更多相关文章

  1. oracle函数返回结果集

    一.用自定义类型实现 1.创建表对象类型. 在Oracle中想要返回表对象,必须自定义一个表类型,如下所示: create or replace type type_table is table of ...

  2. oracle调用存储过程和函数返回结果集

    在程序开发中,常用到返回结果集的存储过程,这个在mysql和sql server 里比较好处理,直接返回查询结果就可以了,但在oracle里面 要 out 出去,就多了一个步骤,对于不熟悉的兄弟们还得 ...

  3. oracle自定义函数返回结果集

    首先要弄两个type,不知道什么鬼: 1. create or replace type obj_table as object ( id ), name ), ) ) 2. create or re ...

  4. oracle pipelined返回值函数 针对数据汇总统计 返回结果集方法

    近期需要一个汇总统计,由于数据太多,数据量太大所以在java程序中实现比较困难.若用后台程序统计,数据不能保证实时,同时实现周期比较长.顾使用函数返回结果集的方式,在不增加临时表的情况下实时获取数据. ...

  5. Oracle中函数如何返回结果集

    在Oracle中,用函数返回结果集有时候要用到,下面是demo: 1 2 3 4 5 6 7 create or replace type t_test as object ( id integer, ...

  6. PostgreSQL函数如何返回数据集 [转]

    PostgreSQL函数如何返回数据集 以下主要介绍PostgreSQL函数/存储过程返回数据集,或者也叫结果集的示例. 背景: PostgreSQL里面没有存储过程,只有函数,其他数据库里的这两个对 ...

  7. Oracle中函数/过程返回结果集的几种方式

    原文 Oracle中函数/过程返回结果集的几种方式 Oracle中函数/过程返回结果集的几种方式:    以函数return为例,存储过程只需改为out参数即可,在oracle 10g测试通过.    ...

  8. Mybatis下配置调用Oracle自定义函数返回的游标结果集

    在ibatis和Mybatis对存储过程和函数函数的调用的配置Xml是不一样的,以下是针对Mybatis 3.2的环境进行操作的. 第一步配置Mapper的xml内容 <mapper names ...

  9. KingbaseES函数如何返回结果集

    函数返回值一般是某一类型值,如int,varchar,date等,返回结果集时就需要用到setof语法. 创建数据 create table class(id number primary key, ...

随机推荐

  1. Java基础知识学习(五)

    高级特性:接口 接口(Interface) 1) 接口中只能定义抽象方法,默认为 public abstract 的,变量可以是static的 2) 接口中没有构造方法 3) 一个接口不实现另一个接口 ...

  2. PMBOK(第五版)学习笔记二-十大知识领域(P87)

    五大项目管理过程组:启动.规划.执行.监控.收尾过程组 十大知识领域是:项目整合管理.项目范围管理.项目时间管理.项目成本管理.项目质量管理.项目人力资源管理.项目沟通管理.项目风险管理.项目采购管理 ...

  3. ADDM Reports bug:Significant virtual memory paging was detected on the host operating system

    查看ADDM(数据库版本为ORACLE 10.2.0.5.0)报告时,发现其中有个结论非常不靠谱:Significant virtual memory paging was detected on t ...

  4. JDK动态代理和CGLIB的区别

    Aspect默认情况下不用实现接口,但对于目标对象,在默认情况下必须实现接口 如果没有实现接口必须引入CGLIB库 我们可以通过Advice中添加一个JoinPoint参数,这个值会由spring自动 ...

  5. ThinkPHP3.1.3源码分析---php文件压缩zlib.output_compression 和 ob_gzhandler

    问题来源:\ThinkPHP3.1.3_full\ThinkPHP\Lib\Core\App.class.php 中 init()方法      if(C('OUTPUT_ENCODE')){     ...

  6. JavaScript中产生标识符方式的演变

    本文记录下JS中产生标示符方式的演变,从ES5到ES6,ES5及其之前是一种方式,只包含两种声明(var/function),ES6则增加了一些产生标识符的关键字,如 let.const.class. ...

  7. Hive分析hadoop进程日志

    想把hadoop的进程日志导入hive表进行分析,遂做了以下的尝试. 关于hadoop进程日志的解析 使用正则表达式获取四个字段,一个是日期时间,一个是日志级别,一个是类,最后一个是详细信息, 然后在 ...

  8. [转]Ionic系列——CodePen上的优秀Ionic_Demo

    本文转自:http://my.oschina.net/u/1416844/blog/514361?fromerr=bbFC5JIl 案例网站 Slidebox with Dynamic Slides ...

  9. 150924-还是起得来床的好-HTML(CSS)

    一早醒来是9:10,这些天最晚的了,也可能是睡的最爽的了. 不废话,早上Matlab仿真干不出来,不如学学html,上代码~ <!DOCTYPE HTML><html>< ...

  10. U3D中GameObject.Find无法找到元件

    U3D中GameObject.Find 如果某元件SetActive(false)了,Find()无法找到 因为Find()只会帮你找出正在活动中的物件,所以在将物件关闭前,我们必须将此物件放至预先定 ...