如何在不保持事务打开的情况下保持结果集?

A-K*_*A-K 5 postgresql pgadmin cursors postgresql-9.3

以下文档描述了如何查看从函数返回的 refcursor,这里,如下所示:

    CREATE FUNCTION reffunc(refcursor) RETURNS refcursor AS '
BEGIN
    OPEN $1 FOR SELECT col FROM test;
    RETURN $1;
END;
' LANGUAGE plpgsql;

BEGIN;
SELECT reffunc('funccursor');
FETCH ALL IN funccursor;
COMMIT;
Run Code Online (Sandbox Code Playgroud)

这对我有用。但是,如果我想将结果保留在我的屏幕上,我必须保持事务处于打开状态。当我执行 COMMIT 时,我的结果集被丢弃。当我同时执行 FETCH 和 COMMIT 时,第一个结果集被丢弃。

有没有办法提交事务但保留结果集?PgAdmin 的版本是 1.18.1。

Dan*_*ité 8

当使用DECLARE在 SQL 级别定义游标时,有一个选项WITH HOLD可以使其在提交当前事务后继续存在。引用文档:

WITH HOLD 指定创建游标的事务提交成功后可以继续使用游标

另一方面,由 plpgsql 函数打开的 refcursor 在事务结束时关闭。引用plpgsql 文档

所有门户都在交易结束时隐式关闭。因此,refcursor 值仅可用于在事务结束之前引用打开的游标。

要在 plpgsql 函数中创建一个可以在其“父”事务之外使用的游标,这只是一个语法问题。您需要游标的 SQL 实现,而不是 plpgsql 变体。为此,EXECUTE必须使用。

举个例子,这里有一个类似于你的函数的框架,但使用了比事务更长的 SQL 级游标:

CREATE FUNCTION dyncursor(name text) RETURNS VOID AS
$$
DECLARE
  query text;
BEGIN
  query='SELECT 1 as col1, 2 as col2'; -- sample query
  EXECUTE 'DECLARE ' || quote_ident(name) || ' CURSOR WITH HOLD FOR ' || query;
END
$$ language plpgsql;
Run Code Online (Sandbox Code Playgroud)

演示:

测试=>开始;
测试 => 选择 dyncursor('foo');
 动力游标 
-----------

(1 行)
测试=>提交;
test=> 从 foo 中获取所有内容;
 列 1 | 列2
------+------
    1 | 2
(1 行)
测试 => 关闭 foo;
关闭光标