↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2
历史版本PostgreSQL 7.3 已于 2007 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

19.7. 游标 #

不是一次执行整个查询,而是可以建立一个封装该查询的 游标,然后每次读取查询结果的少数几行。这样做的一个 原因是避免结果包含大量行时的内存溢出。(不过, PL/pgSQL 用户通常不需要担心这一点,因为 FOR 循环内部自动使用游标来避免内存问题。)更有趣的用法是返回函数 所创建游标的引用,让调用者读取这些行。这提供了一种从函数返回大型 行集的高效方式。

19.7.1. 声明游标变量 #

PL/pgSQL 中对游标的所有访问都通过游标 变量进行,游标变量总是属于特殊数据类型 refcursor。创建游标 变量的一种方法是直接把它声明为 refcursor 类型的变量。另一 种方法是使用游标声明语法,其一般形式为:

name CURSOR [ ( arguments ) ] FOR select_query ;

(为兼容 Oracle,FOR 可以换成 IS。) arguments(如果有)是一个由 name datatype 对组成的逗号分隔列表,这些名称在给定查询中将被参数值替换。替换这些 名称的实际值将在游标打开时指定。

一些例子:

DECLARE
    curs1 refcursor;
    curs2 CURSOR FOR SELECT * from tenk1;
    curs3 CURSOR (key int) IS SELECT * from tenk1 where unique1 = key;

这三个变量的数据类型都是 refcursor,但第一个可用于任何 查询,第二个已有完全指定的查询绑定于其上,最后一个 有一个参数化查询绑定于其上。(打开游标时,key 将被替换 为一个整数参数值。)变量 curs1 被称为 未绑定的,因为它没有绑定到任何特定查询。

19.7.2. 打开游标 #

游标可以用来检索行之前,必须先被打开。(这等价于 SQL 命令 DECLARE CURSOR。)PL/pgSQL 有四种形式的 OPEN 语句,其中两种使用未绑定游标变量,另外两种使用 绑定游标变量。

19.7.2.1. OPEN FOR SELECT

OPEN unbound-cursor FOR SELECT ...;

游标变量被打开并被给定要执行的指定查询。游标不能已经处于打开 状态,而且它必须被声明为未绑定游标(即简单的 refcursor 变量)。SELECT 查询的处理方式与 PL/pgSQL 中其他 SELECT 语句相同:替换 PL/pgSQL 变量名,并缓存查询计划供可能 的重用。

OPEN curs1 FOR SELECT * FROM foo WHERE key = mykey;

19.7.2.2. OPEN FOR EXECUTE

OPEN unbound-cursor FOR EXECUTE query-string;

游标变量被打开并被给定要执行的指定查询。游标不能已经处于打开 状态,而且它必须被声明为未绑定游标(即简单的 refcursor 变量)。查询以与 EXECUTE 命令中相同的方式指定为 字符串表达式。与通常一样,这提供了灵活性,使查询可以随每次运行 而变化。

OPEN curs1 FOR EXECUTE ''SELECT * FROM '' || quote_ident($1);

19.7.2.3. 打开绑定游标

OPEN bound-cursor [ ( argument_values ) ];

这种形式的 OPEN 用于打开其查询在声明时就绑定于其上的游标变量。 游标不能已经处于打开状态。当且仅当游标被声明为接受参数时,必须 出现实参值表达式列表。这些值将在查询中被替换。绑定游标的查询计划 总是被视为可缓存的——这种情况没有 EXECUTE 的等价物。

OPEN curs2;
OPEN curs3(42);

19.7.3. 使用游标 #

游标一旦被打开,就可以用这里描述的语句操纵它。

这些操纵不必发生在最初打开游标的同一个函数中。你可以从函数中返回 refcursor 值,让调用者操作该游标。(在内部, refcursor 值只是包含该游标活动查询的 Portal 的字符串名称。 这个名称可以被传递、赋给其他 refcursor 变量等等,而不会 干扰 Portal。)

所有 Portal 都在事务结束时隐式关闭。因此 refcursor 值只在 事务结束之前可用于引用打开的游标。

19.7.3.1. FETCH

FETCH cursor INTO target;

FETCH 从游标检索下一行到目标中,目标可以是行变量、记录变量或 简单变量的逗号分隔列表,就像 SELECT INTO 一样。与 SELECT INTO 一样,可以检查特殊变量 FOUND 来看是否取得了行。

FETCH curs1 INTO rowvar;
FETCH curs2 INTO foo,bar,baz;

19.7.3.2. CLOSE

CLOSE cursor;

CLOSE 关闭打开游标底层的 Portal。这可用于在事务结束之前释放 资源,或释放游标变量以便再次打开。

CLOSE curs1;

19.7.3.3. 返回游标

PL/pgSQL 函数可以向调用者返回游标。 这用于从函数返回多行或多列。函数打开游标并把游标名返回给调用者。 然后调用者可以从游标中获取行。游标可以由调用者关闭,也可以在 事务关闭时自动关闭。

函数返回的游标名可以由调用者指定,也可以自动生成。下面的例子 展示了如何由调用者提供游标名:

CREATE TABLE test (col text);
INSERT INTO test VALUES ('123');

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;

下面的例子使用自动游标名生成:

CREATE FUNCTION reffunc2() RETURNS refcursor AS '
DECLARE
        ref refcursor;
BEGIN
        OPEN ref FOR SELECT col FROM test;
        RETURN ref;
END;
' LANGUAGE 'plpgsql';

BEGIN;
SELECT reffunc2();
  
        reffunc2      
  --------------------
   <unnamed cursor 1>
  (1 row)

FETCH ALL IN "<unnamed cursor 1>";
COMMIT;

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。