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 标准兼容而接受。将
INSENSITIVE
与FOR UPDATE
或FOR 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
关键字ASENSITIVE
、BINARY
、INSENSITIVE
和SCROLL
可以按任何顺序出现。
注意
普通游标以文本格式返回数据,与SELECT
生成的相同。BINARY
选项指定游标应以二进制格式返回数据。这减少了服务器和客户端的转换工作量,但增加了程序员处理与平台相关的二进制数据格式的工作量。例如,如果查询从整数列返回一个值,则使用默认游标将获得一个1
字符串,而使用二进制游标将获得一个包含该值内部表示形式的 4 字节字段(采用大端字节序)。
应谨慎使用二进制游标。许多应用程序(包括psql)都没有准备好处理二进制游标,并希望以文本格式返回数据。
注意
当客户端应用程序使用“扩展查询”协议发出FETCH
命令时,绑定协议消息指定是要以文本格式还是二进制格式检索数据。此选择将覆盖游标的定义方式。因此,在使用扩展查询协议时,二进制游标的概念已过时——任何游标都可以被视为文本或二进制。
除非指定WITH HOLD
,否则此命令创建的游标只能在当前事务中使用。因此,在事务块之外,不带WITH HOLD
的DECLARE
是无用的:游标只能保留到语句完成。因此,如果在事务块之外使用此类命令,PostgreSQL会报告错误。使用BEGIN
和COMMIT
(或ROLLBACK
)来定义事务块。
如果指定了WITH HOLD
,并且创建游标的事务成功提交,则后续事务在同一会话中可以继续访问该游标。(但如果创建事务被中止,则游标将被移除。)使用WITH HOLD
创建的游标在对它发出显式CLOSE
命令或会话结束时关闭。在当前实现中,由保持的游标表示的行被复制到临时文件或内存区域,以便它们可用于后续事务。
当查询包含FOR UPDATE
或FOR SHARE
时,可能无法指定WITH HOLD
。
在定义将用于向后获取的游标时,应指定SCROLL
选项。这是 SQL 标准的要求。但是,为了与早期版本兼容,PostgreSQL将允许在没有SCROLL
的情况下向后获取,如果游标的查询计划足够简单,则无需额外的开销来支持它。但是,建议应用程序开发人员不要依赖于从未使用SCROLL
创建的游标中使用向后获取。如果指定了NO SCROLL
,则无论如何都禁止向后获取。
当查询包含FOR UPDATE
或FOR SHARE
时,也禁止向后获取;因此在这种情况下可能无法指定SCROLL
。
注意
如果可滚动游标调用任何不稳定函数(请参阅第 38.7 节),则它们可能会产生意外的结果。当重新获取先前获取的行时,可能会重新执行这些函数,这可能会导致与第一次不同的结果。最好为涉及不稳定函数的查询指定NO SCROLL
。如果这不可行,一种解决方法是声明游标SCROLL WITH HOLD
,并在从其中读取任何行之前提交事务。这将强制游标的整个输出在临时存储中实现,以便为每一行只执行一次不稳定函数。
如果游标的查询包含FOR UPDATE
或FOR SHARE
,则返回的行会在首次获取时锁定,就像带有这些选项的常规SELECT
命令一样。此外,返回的行将是最新的版本。
注意
通常建议在打算将游标与UPDATE ... WHERE CURRENT OF
或DELETE ... WHERE CURRENT OF
一起使用时使用FOR UPDATE
。使用FOR UPDATE
可防止其他会话在获取行和更新行之间更改这些行。如果没有FOR UPDATE
,如果自创建游标以来行已更改,则后续WHERE CURRENT OF
命令将不起作用。
使用FOR UPDATE
的另一个原因是,如果没有它,如果游标查询不满足 SQL 标准的规则,即“简单可更新”(特别是,游标必须仅引用一个表,且不使用分组或ORDER BY
),则后续WHERE CURRENT OF
可能会失败。根据计划选择详细信息,不可简单更新的游标可能起作用,也可能不起作用;因此,在最坏的情况下,应用程序可能在测试中起作用,但在生产中失败。如果指定了FOR UPDATE
,则保证游标可更新。
不将FOR UPDATE
与WHERE CURRENT OF
一起使用的主要原因是,如果您需要游标可滚动或与并发更新隔离(即继续显示旧数据)。如果这是必需的,请密切注意上面显示的注意事项。
SQL 标准仅为嵌入式SQL中的游标做出规定。PostgreSQL服务器未为游标实现OPEN
语句;游标在声明时被认为是打开的。但是,PostgreSQL的嵌入式 SQL 预处理器ECPG支持标准 SQL 游标约定,包括涉及DECLARE
和OPEN
语句的约定。
底层打开游标的服务器数据结构称为门户。门户名称在客户端协议中公开:如果客户端知道门户名称,则它可以直接从打开的门户中获取行。使用DECLARE
创建游标时,门户名称与游标名称相同。
您可以通过查询pg_cursors
系统视图来查看所有可用的游标。
示例
声明游标
DECLARE liahona CURSOR FOR SELECT * FROM films;
有关游标用法的更多示例,请参见FETCH。
兼容性
SQL 标准仅允许在嵌入式SQL和模块中使用游标。PostgreSQL允许交互式使用游标。
根据 SQL 标准,由UPDATE ... WHERE CURRENT OF
和DELETE ... WHERE CURRENT OF
语句对不敏感游标所做的更改在同一游标中可见。PostgreSQL将这些语句视为所有其他数据更改语句,因为它们在不敏感游标中不可见。
二进制游标是PostgreSQL扩展。