2024年9月26日:PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不受支持的版本: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 / 7.1

DECLARE

DECLARE — 定义游标

概要

DECLARE name [ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ]
    CURSOR [ { WITH | WITHOUT } HOLD ] FOR query

描述

DECLARE 允许用户创建游标,可用于从更大的查询中一次检索少量行。创建游标后,使用 FETCH 从中获取行。

注意

此页面描述了在 SQL 命令级别使用游标。如果您尝试在 PL/pgSQL 函数内部使用游标,则规则有所不同,请参阅 第 41.7 节

参数

name

要创建的游标的名称。此名称必须与会话中任何其他活动游标名称不同。

BINARY

导致游标以二进制而不是文本格式返回数据。

ASENSITIVE
INSENSITIVE

游标敏感性决定了在声明游标后,在同一事务中对游标底层数据所做的更改是否在游标中可见。INSENSITIVE 表示不可见,ASENSITIVE 表示行为取决于实现。第三种行为,SENSITIVE,表示此类更改在游标中可见,在 PostgreSQL 中不可用。在 PostgreSQL 中,所有游标都是不敏感的;因此,这些关键字没有效果,仅为了与 SQL 标准兼容而被接受。

INSENSITIVEFOR UPDATEFOR SHARE 结合使用会导致错误。

SCROLL
NO SCROLL

SCROLL 指定游标可用于以非顺序方式(例如,向后)检索行。根据查询执行计划的复杂性,指定 SCROLL 可能会对查询的执行时间造成性能损失。NO SCROLL 指定游标不能用于以非顺序方式检索行。默认情况下,某些情况下允许滚动;这与指定 SCROLL 不同。有关详细信息,请参见下面的 注释

WITH HOLD
WITHOUT HOLD

WITH HOLD 指定在创建它的事务成功提交后,可以继续使用该游标。WITHOUT HOLD 指定在创建它的事务之外无法使用该游标。如果既未指定 WITHOUT HOLD 也未指定 WITH HOLD,则默认为 WITHOUT HOLD

query

一个 SELECTVALUES 命令,它将提供游标要返回的行。

关键字 ASENSITIVEBINARYINSENSITIVESCROLL 可以按任何顺序出现。

注释

普通游标以文本格式返回数据,与 SELECT 生成的结果相同。BINARY 选项指定游标应以二进制格式返回数据。这减少了服务器和客户端的转换工作,但增加了程序员处理平台相关的二进制数据格式的工作量。例如,如果查询从整数列返回一个值 1,则使用默认游标将获得字符串 1,而使用二进制游标将获得包含该值内部表示形式的 4 字节字段(以大端字节序)。

应谨慎使用二进制游标。许多应用程序(包括 psql)无法处理二进制游标,并期望数据以文本格式返回。

注意

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

除非指定了 WITH HOLD,否则此命令创建的游标只能在当前事务中使用。因此,在事务块之外使用不带 WITH HOLDDECLARE 是没有意义的:游标只能存活到语句完成为止。因此,如果在事务块之外使用此类命令,PostgreSQL 会报告错误。使用 BEGINCOMMIT(或 ROLLBACK)来定义事务块。

如果指定了 WITH HOLD 并且创建游标的事务成功提交,则后续事务可以在同一会话中继续访问该游标。(但如果创建事务中止,则游标将被删除。)当对创建具有 WITH HOLD 的游标发出显式 CLOSE 命令或会话结束时,该游标将关闭。在当前实现中,保持的游标所表示的行将复制到临时文件或内存区域,以便它们对后续事务可用。

当查询包含 FOR UPDATEFOR SHARE 时,不得指定 WITH HOLD

当定义将用于向后获取的游标时,应指定 SCROLL 选项。SQL 标准要求这样做。但是,为了与早期版本兼容,PostgreSQL 允许在没有 SCROLL 的情况下进行向后获取,如果游标的查询计划足够简单,则无需额外的开销来支持它。但是,建议应用程序开发人员不要依赖于从未创建具有 SCROLL 的游标中进行向后获取。如果指定了 NO SCROLL,则在任何情况下都不允许向后获取。

当查询包含 FOR UPDATEFOR SHARE 时,也不允许向后获取;因此,在这种情况下不得指定 SCROLL

注意

如果可滚动游标调用任何易变函数(请参阅 第 36.7 节),则可能会产生意外结果。当重新获取先前获取的行时,可能会重新执行函数,这可能会导致与第一次不同的结果。最好为涉及易变函数的查询指定 NO SCROLL。如果这不可行,则一种解决方法是将游标声明为 SCROLL WITH HOLD 并在读取游标中的任何行之前提交事务。这将强制将游标的整个输出具体化到临时存储中,以便每个行的易变函数都执行一次。

如果游标的查询包含 FOR UPDATEFOR SHARE,则在第一次获取返回的行时锁定这些行,这与包含这些选项的常规 SELECT 命令相同。此外,返回的行将是最新的版本。

注意

如果打算将游标与 UPDATE ... WHERE CURRENT OFDELETE ... WHERE CURRENT OF 一起使用,则通常建议使用 FOR UPDATE。使用 FOR UPDATE 可以防止其他会话在获取行到更新行之间更改这些行。如果没有 FOR UPDATE,如果自创建游标以来已更改了该行,则后续的 WHERE CURRENT OF 命令将不起作用。

使用 FOR UPDATE 的另一个原因是,如果没有它,如果游标查询不满足 SQL 标准关于“简单可更新”(特别是,游标必须仅引用一个表,并且不使用分组或 ORDER BY)的规则,则后续的 WHERE CURRENT OF 可能会失败。不可简单更新的游标可能会工作,也可能不会工作,具体取决于计划选择细节;因此,在最坏的情况下,应用程序可能会在测试中工作,然后在生产中失败。如果指定了 FOR UPDATE,则保证游标是可更新的。

不与 WHERE CURRENT OF 一起使用 FOR UPDATE 的主要原因是,如果您需要游标可滚动或与并发更新隔离(即继续显示旧数据)。如果这是必需的,请密切注意上面显示的警告。

SQL 标准仅对嵌入式游标做出规定SQL

. PostgreSQL 服务器没有实现用于游标的 OPEN 语句;游标在声明时就被认为是打开的。但是,ECPGPostgreSQL 的嵌入式 SQL 预处理器)支持标准 SQL 游标约定,包括涉及 DECLAREOPEN 语句的那些约定。

一个打开的游标底层的服务器数据结构称为 Portal(门户)。门户名称在客户端协议中公开:如果客户端知道门户名称,则可以直接从打开的门户中提取行。使用 DECLARE 创建游标时,门户名称与游标名称相同。

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

示例

声明游标

DECLARE liahona CURSOR FOR SELECT * FROM films;

有关游标用法的更多示例,请参阅 FETCH

兼容性

SQL 标准仅允许在嵌入式SQL

和模块中使用游标。PostgreSQL 允许交互式使用游标。

根据 SQL 标准,通过 UPDATE ... WHERE CURRENT OFDELETE ... WHERE CURRENT OF 语句对不敏感游标所做的更改在同一游标中可见。PostgreSQL 将这些语句视为所有其他数据更改语句,因为它们在不敏感游标中不可见。

二进制游标是 PostgreSQL 的扩展。

另请参阅

CLOSEFETCHMOVE

提交更正

如果您在文档中发现任何不正确的内容,与您对特定功能的体验不符,或者需要进一步说明,请使用 此表单 报告文档问题。