返回结果集
您可以使用游标或临时表返回结果集。
返回游标
要返回游标,请创建一个过程,该过程具有通过 refcursor
数据类型定义的 INOUT 参数。在调用过程时,向游标提供一个名称。然后,您就可以按名称从游标提取结果。
以下示例创建名为 get_result_set
的过程,该过程具有名为 rs_out
的 INOUT 参数,使用 refcursor
数据类型。该过程使用 SELECT 语句打开游标。
CREATE OR REPLACE PROCEDURE get_result_set (param IN integer, rs_out INOUT refcursor) AS $$ BEGIN OPEN rs_out FOR SELECT * FROM fact_tbl where id >= param; END; $$ LANGUAGE plpgsql;
以下 CALL 命令打开名为 mycursor
的游标。仅在事务中使用游标。
BEGIN; CALL get_result_set(1, 'mycursor');
打开游标之后,您可以从游标中提取数据,如下例所示。
FETCH ALL FROM mycursor; id | secondary_id | name -------+--------------+--------- 1 | 1 | Joe 1 | 2 | Ed 2 | 1 | Mary 1 | 3 | Mike (4 rows)
最后,事务完成或回退。
COMMIT;
存储过程返回的游标需要遵循与 DECLARE CURSOR 中所述相同的约束和性能注意事项。有关更多信息,请参阅游标约束。
以下示例演示从 JDBC,使用 get_result_set
数据类型调用 refcursor
存储过程。文本 'mycursor'
(游标的名称)传递到 prepareStatement
。结果提取自 ResultSet
。
static void refcursor_example(Connection conn) throws SQLException { conn.setAutoCommit(false); PreparedStatement proc = conn.prepareStatement("CALL get_result_set(1, 'mycursor')"); proc.execute(); ResultSet rs = statement.executeQuery("fetch all from mycursor"); while (rs.next()) { int n = rs.getInt(1); System.out.println("n " + n); }
使用临时表
要返回结果,您可以将句柄返回到包含结果行的临时表。客户端可以向存储过程提供名称作为参数。在存储过程内部,可以使用动态 SQL 在临时表上执行操作。下面是一个示例。
CREATE PROCEDURE get_result_set(param IN integer, tmp_name INOUT varchar(256)) as $$ DECLARE row record; BEGIN EXECUTE 'drop table if exists ' || tmp_name; EXECUTE 'create temp table ' || tmp_name || ' as select * from fact_tbl where id <= ' || param; END; $$ LANGUAGE plpgsql; CALL get_result_set(2, 'myresult'); tmp_name ----------- myresult (1 row) SELECT * from myresult; id | secondary_id | name ----+--------------+------ 1 | 1 | Joe 2 | 1 | Mary 1 | 2 | Ed 1 | 3 | Mike (4 rows)