DECLARE

定义一个游标。

概要

DECLARE <name> [BINARY] [INSENSITIVE] [NO SCROLL] [PARALLEL RETRIEVE] CURSOR 
     [{WITH | WITHOUT} HOLD] 
     FOR <query>

描述

DECLARE 允许用户创建游标,该游标可用于从大型查询中每次提取少量行。游标可通过 FETCH 返回数据。

注意! 本页描述了在SQL命令层级使用游标的方法。若需在PL/pgSQL函数内部使用游标,其规则有所不同,请参阅PL/pgSQL文档。

常规游标以文本格式返回数据,与SELECT语句的输出形式相同。由于数据原生存储于二进制格式,系统必须进行转换才能生成文本格式。当信息以文本形式返回后,客户端应用程序可能需要将其转换为二进制格式以便操作。此外,文本格式的数据通常比二进制格式占用更大空间。二进制游标以二进制表示形式返回数据,便于操作。但若您最终仍需以文本形式显示数据,采用文本形式检索可在客户端节省处理工作量。

例如,若查询从整数列返回值为1,使用默认游标时将获得字符串"1",而使用二进制游标时则会获得包含该值内部表示形式(采用大端字节序)的4字节字段。

二进制游标需谨慎使用。包括psql在内的许多应用程序尚未准备好处理二进制游标,它们期望返回的数据采用文本格式。

注意! 当客户端应用程序使用"扩展查询"协议发出FETCH命令时,绑定协议消息会指定数据应以文本还是二进制格式检索。此选择将覆盖游标的定义方式。因此在使用扩展查询协议时,二进制游标的概念已过时——任何游标均可视为文本或二进制类型。

UPDATEDELETE语句的WHERE CURRENT OF子句中可指定游标,用于更新或删除表数据。UPDATE或DELETE语句仅能在服务器端执行,例如交互式psql会话或脚本中。

并行检索游标

数据库支持一种特殊的游标类型——并行检索游标。您可以使用并行检索游标直接从数据库段并行检索查询结果,从而绕过协调器。

并行检索游标不支持WITH HOLD子句。当您声明并行检索游标时,数据库将忽略BINARY子句。

需为每个并行检索游标端点开启专用检索会话,并通过RETRIEVE命令从并行检索游标中获取查询结果。

参数

  • name

    • 要创建的游标名称。
  • BINARY

    • 使游标返回二进制数据而非文本格式数据。

      注意! 当声明并行检索游标时,数据库将忽略BINARY子句。

  • 不敏感

    • 表示从游标检索的数据不受游标创建后底层表更新的影响。在数据库中,所有游标均为不敏感。该关键字目前无效,仅为兼容SQL标准而保留。
  • NO SCROLL

    • 游标不可用于非顺序方式检索行。此为数据库默认行为;不支持可滚动游标(SCROLL)。
  • PARALLEL RETRIEVE

    • 声明并行检索游标。并行检索游标是一种特殊类型的游标,可用于并行直接从数据库分段中检索结果。
  • WITH HOLD

  • WITHOUT HOLD

    • WITH HOLD 表示游标在创建事务成功提交后仍可继续使用。WITHOUT HOLD 表示游标仅限于创建事务内部使用。默认值为 WITHOUT HOLD。

      注意! 数据库不支持带WITH HOLD子句声明并行检索游标。当查询包含FOR UPDATE或FOR SHARE子句时,亦不可指定WITH HOLD。

  • 查询

    • 用于提供游标将返回的行数据的 SELECTVALUES 命令。

    • 若在 UPDATE 或 DELETE 命令的 WHERE CURRENT OF 子句中使用游标,则 SELECT 命令必须满足以下条件:

    • 不能引用视图或外部表。

    • 仅引用一张表。

    • 该表必须为堆表,且不得为复制分布式表(不得为视图、外部表或追加优化列式表)。

    • 不能包含以下任何内容:

      • 分组子句
      • 集合运算(如 UNION ALL 或 UNION DISTINCT)
      • 排序子句
      • 窗口子句
      • 联接或自联接
    • 在SELECT命令中指定FOR UPDATE子句可防止其他会话在获取行与更新行之间的时间段内修改该行。若未使用FOR UPDATE子句,当游标创建后行被修改时,后续使用带WHERE CURRENT OF子句的UPDATE或DELETE命令将无效。

    注意:在SELECT命令中指定FOR UPDATE子句将锁定整个表,而非仅锁定选定的行。 关键字BINARY、INSENSITIVE和NO SCROLL的出现顺序不限。

注意

除非指定 WITH HOLD,否则本命令创建的游标仅能在当前事务内使用。因此,在事务块之外,未带 WITH HOLD 的 DECLARE 毫无意义:游标仅存活至语句执行完毕。故若在事务块外使用此命令,数据库将报告错误。请使用 BEGIN 和 COMMIT(或 ROLLBACK)定义事务块。

若指定WITH HOLD且创建游标的事务成功提交,后续事务可在同一会话中继续访问该游标(但若创建事务提前终止,游标将被移除)。带WITH HOLD创建的游标将在显式执行CLOSE命令或会话结束时关闭。在当前实现中,持有的游标所代表的行会被复制到临时文件或内存区域,以便后续事务可继续使用。

若在事务中使用DECLARE命令创建游标,则必须先用CLOSE命令关闭游标,才能在该事务中使用SET命令。

数据库目前不支持可滚动游标。您只能使用 FETCH 或 RETRIEVE 向前移动游标位置,无法向后移动。

DECLARE...FOR UPDATE 不支持追加优化表。

可通过查询 pg_cursors 系统视图查看所有可用游标。

示例

声明一个游标:

DECLARE mycursor CURSOR FOR SELECT * FROM mytable;

为同一查询声明并行检索游标:

DECLARE myprcursor PARALLEL RETRIEVE CURSOR FOR SELECT * FROM mytable;

兼容性

SQL标准仅允许在嵌入式SQL和模块中使用游标。本数据库允许交互式使用游标。

本数据库未实现游标的OPEN语句。游标在声明时即视为已打开。

SQL标准允许游标向前向后移动。本数据库所有游标均为仅向前移动(不可滚动)。

二进制游标是本数据库的扩展功能。

SQL标准未对并行检索游标作出规定。

另见

CLOSE, DELETE, FETCH, MOVE, RETRIEVE, SELECT, UPDATE