Skip to content

DECLARE

DECLARE — 定义游标

语法

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

描述

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

注意

此页面描述了在 SQL 命令级别使用游标。如果您尝试在PL/pgSQL函数中使用游标,则规则不同 — 请参见第 43.7 节

参数

name

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

BINARY

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

ASENSITIVE
INSENSITIVE

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

INSENSITIVEFOR UPDATEFOR SHARE 一起指定是一个错误。

SCROLL
NO SCROLL

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

WITH HOLD
WITHOUT HOLD

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

query

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

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

注意

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

应谨慎使用二进制游标。许多应用程序(包括psql)都没有准备好处理二进制游标,并希望以文本格式返回数据。

注意

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

除非指定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

注意

如果可滚动游标调用任何不稳定函数(请参阅第 38.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 标准仅为嵌入式SQL中的游标做出规定。PostgreSQL服务器未为游标实现OPEN语句;游标在声明时被认为是打开的。但是,PostgreSQL的嵌入式 SQL 预处理器ECPG支持标准 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扩展。

另请参阅

CLOSEFETCHMOVE