支持的版本: 当前 (17) / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 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 / 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 HOLDWITH HOLD,则默认值为 WITHOUT HOLD

query

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

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

备注

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

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

注意

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

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

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

当查询包含 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,则保证游标是可更新的。

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

SQL 标准仅为嵌入式游标提供规定SQLPostgreSQL 服务器没有实现游标的 OPEN 语句;游标在声明时被认为是打开的。但是,ECPGPostgreSQL 的嵌入式 SQL 预处理器,支持标准 SQL 游标约定,包括涉及 DECLAREOPEN 语句的约定。

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

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

示例

要声明游标

DECLARE liahona CURSOR FOR SELECT * FROM films;

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

兼容性

SQL 标准只允许在嵌入式中使用游标SQL和模块中。PostgreSQL 允许以交互方式使用游标。

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

二进制游标是 PostgreSQL 的扩展。

另请参阅

CLOSE, FETCH, MOVE

提交更正

如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步澄清的地方,请使用 此表单 报告文档问题。