On this page
Note
DECLARE
DECLARE —定义一个游标
Synopsis
DECLARE name [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ]
CURSOR [ { WITH | WITHOUT } HOLD ] FOR query
Description
DECLARE
允许用户创建游标,这些游标可用于一次从较大查询中检索少量行。创建游标后,使用FETCH从中获取行。
Note
本页在 SQL 命令级别描述游标的用法。如果您尝试在 PL/pgSQL 函数中使用游标,则规则有所不同—参见Section 43.7。
Parameters
name
- 要创建的游标的名称。
BINARY
- 使光标返回二进制而不是文本格式的数据。
INSENSITIVE
- 指示从游标中检索到的数据应不受创建游标后对游标基础表的更新的影响。在 PostgreSQL 中,这是默认行为。因此,此关键字无效,仅接受与 SQL 标准的兼容性。
SCROLL
NO SCROLL
SCROLL
指定可以使用游标以非连续方式(例如,向后)检索行。根据查询执行计划的复杂程度,指定SCROLL
可能会影响查询的执行时间。NO SCROLL
指定不能使用游标以非 Sequences 方式检索行。默认情况下允许滚动。这与指定SCROLL
不同。有关详情,请参见Notes。
WITH HOLD
WITHOUT HOLD
WITH HOLD
指定在成功提交创建游标的事务后可以 continue 使用游标。WITHOUT HOLD
指定不能在创建游标的事务之外使用游标。如果未指定WITHOUT HOLD
或WITH HOLD
,则默认为WITHOUT HOLD
。
query
关键字BINARY
,INSENSITIVE
和SCROLL
可以按任何 Sequences 出现。
Notes
普通游标以文本格式返回数据,与SELECT
相同。 BINARY
选项指定游标应以二进制格式返回数据。这减少了服务器和 Client 端的转换工作,但以程序员更多的精力来处理依赖于平台的二进制数据格式为代价。例如,如果查询从整数列返回值 1,则将使用默认游标获得1
的字符串,而使用二进制游标将获得包含该值的内部表示形式的 4 字节字段(以大端字节序)。
二进制游标应谨慎使用。许多应用程序,包括 psql,都不准备处理二进制游标,并期望数据以文本格式返回。
Note
当 Client 端应用程序使用“扩展查询”协议发出FETCH
命令时,绑定协议消息将指定是以文本还是二进制格式检索数据。此选择将覆盖定义光标的方式。因此,当使用扩展查询协议时,二进制游标的概念就已过时了-任何游标都可以视为文本或二进制。
除非指定WITH HOLD
,否则此命令创建的游标只能在当前事务中使用。因此,DECLARE
而不是WITH HOLD
在事务块之外是无用的:游标将仅生存到语句完成。因此,如果在事务块外使用这样的命令,PostgreSQL 将报告错误。使用BEGIN和COMMIT(或ROLLBACK)定义事务块。
如果指定了WITH HOLD
并且成功提交了创建游标的事务,则该游标可以 continue 被同一会话中的后续事务访问。 (但是,如果创建事务被中止,则删除游标.)当在其上发出显式CLOSE
命令或会话结束时,使用WITH HOLD
创建的游标将关闭。在当前实现中,由保留的游标表示的行被复制到临时文件或存储区中,以便它们可用于后续事务。
当查询包含FOR UPDATE
或FOR SHARE
时,不能指定WITH HOLD
。
定义用于向后取回的游标时,应指定SCROLL
选项。这是 SQL 标准所必需的。但是,为了与早期版本兼容,如果游标的查询计划足够简单,不需要任何额外开销来支持它,则 PostgreSQL 将允许不使用SCROLL
进行向后取回。但是,建议应用程序开发人员不要依赖未使用SCROLL
创建的游标使用向后取回。如果指定NO SCROLL
,则无论如何都不允许向后取。
当查询包含FOR UPDATE
或FOR SHARE
时,也不允许向后抓取;因此在这种情况下可能无法指定SCROLL
。
Caution
如果可滚动游标和WITH HOLD
游标调用任何易失函数(请参见Section 38.7),它们可能会产生意外结果。当重新获取先前获取的行时,这些函数可能会重新执行,可能导致结果与第一次有所不同。在这种情况下,一种解决方法是声明游标WITH HOLD
并提交事务,然后再从中读取任何行。这将强制将光标的整个输出在临时存储中实现,以便对每行仅对易失函数执行一次。
如果游标的查询包含FOR UPDATE
或FOR SHARE
,则返回的行在首次获取时将被锁定,其方式与带有这些选项的常规SELECT命令的方式相同。此外,返回的行将是最新版本;因此,这些选项提供了与 SQL 标准所谓的“敏感游标”等效的功能。 (同时指定INSENSITIVE
和FOR UPDATE
或FOR SHARE
是错误的.)
Caution
如果要与UPDATE ... WHERE CURRENT OF
或DELETE ... WHERE CURRENT OF
一起使用光标,通常建议使用FOR UPDATE
。使用FOR UPDATE
可防止其他会话在获取行和更新行之间更改行。没有FOR UPDATE
,如果自创建游标以来更改了行,则随后的WHERE CURRENT OF
命令将无效。
使用FOR UPDATE
的另一个原因是,没有它,如果游标查询不符合 SQL 标准的“可简单更新”的规则,则随后的WHERE CURRENT OF
可能会失败(特别是,游标必须仅引用一个表并且不使用分组或ORDER BY
) 。根据计划选择的详细信息,不能简单更新的游标可能会起作用,也可能不会起作用。因此在最坏的情况下,应用程序可能会在测试中工作,然后在 Producing 失败。如果指定FOR UPDATE
,则保证游标是可更新的。
不将FOR UPDATE
与WHERE CURRENT OF
结合使用的主要原因是,如果您需要光标可滚动或对后续更新不敏感(即 continue 显示旧数据)。如果这是必需的,请密切注意上面显示的警告。
SQL 标准仅对嵌入式 SQL 中的游标进行规定。 PostgreSQL 服务器不为游标实现OPEN
语句;当游标被声明时,它被认为是打开的。但是,ECPG 是 PostgreSQL 的嵌入式 SQL 预处理程序,支持标准的 SQL 游标约定,包括涉及DECLARE
和OPEN
语句的约定。
您可以通过查询pg_cursors系统视图来查看所有可用的游标。
Examples
声明游标:
DECLARE liahona CURSOR FOR SELECT * FROM films;
有关游标用法的更多示例,请参见FETCH。
Compatibility
SQL 标准说,默认情况下,游标是否对基础数据的并发更新敏感,这取决于实现。在 PostgreSQL 中,游标默认情况下是不敏感的,可以通过指定FOR UPDATE
使其敏感。其他产品可能会有所不同。
SQL 标准仅允许在嵌入式 SQL 和模块中使用游标。 PostgreSQL 允许交互使用游标。
二进制游标是 PostgreSQL 扩展。