DECLARE — 定义一个游标
DECLAREname
[ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ] CURSOR [ { WITH | WITHOUT } HOLD ] FORquery
DECLARE
允许用户创建游标,它可用于一次从较大的查询中检索少量行。 创建游标后,使用 FETCH
从中提取行。
此页面描述了 SQL 命令级别游标的使用。 如果您尝试在 PL/pgSQL 函数内部使用游标,则规则有所不同 — 请参阅第 41.7 节。
name
要创建的游标的名称。 它必须与会话中任何其他活动的游标名称不同。
BINARY
使游标以二进制而不是文本格式返回数据。
ASENSITIVE
INSENSITIVE
游标敏感度决定了在同一事务中,在声明游标后,对游标底层数据所做的更改是否在游标中可见。INSENSITIVE
表示它们不可见,ASENSITIVE
表示该行为取决于实现。第三种行为 SENSITIVE
表示此类更改在游标中可见,在 PostgreSQL 中不可用。 在 PostgreSQL 中,所有游标都不敏感;因此,这些关键字没有任何作用,仅为了与 SQL 标准兼容而被接受。
将 INSENSITIVE
与 FOR UPDATE
或 FOR SHARE
一起指定是错误的。
SCROLL
NO SCROLL
SCROLL
指定游标可用于以非顺序方式检索行(例如,向后)。根据查询执行计划的复杂性,指定 SCROLL
可能会给查询的执行时间带来性能损失。NO SCROLL
指定游标不能用于以非顺序方式检索行。默认情况下允许在某些情况下滚动;这与指定 SCROLL
不同。 有关详细信息,请参阅下面的备注。
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
命令时,Bind 协议消息指定是要以文本还是二进制格式检索数据。此选择将覆盖游标的定义方式。因此,当使用扩展查询协议时,二进制游标的概念已过时 — 任何游标都可以视为文本或二进制。
除非指定了 WITH HOLD
,否则此命令创建的游标只能在当前事务中使用。 因此,在事务块外部使用没有 WITH HOLD
的 DECLARE
是无用的:游标仅在语句完成后才会存在。 因此,如果在事务块外部使用此类命令,PostgreSQL 将报告错误。 使用 BEGIN
和 COMMIT
(或 ROLLBACK
)来定义事务块。
如果指定了 WITH HOLD
并且创建游标的事务成功提交,则同一会话中的后续事务可以继续访问该游标。(但如果创建事务被中止,则会删除游标。) 当对其发出显式的 CLOSE
命令或会话结束时,以 WITH HOLD
创建的游标会关闭。 在当前实现中,由已保留游标表示的行被复制到临时文件或内存区域中,以便它们对于后续事务保持可用。
当查询包含 FOR UPDATE
或 FOR SHARE
时,可能不会指定 WITH HOLD
。
应在定义将用于向后提取的游标时指定 SCROLL
选项。这是 SQL 标准的要求。但是,为了与早期版本兼容,如果游标的查询计划足够简单,不需要额外的开销来支持它,PostgreSQL 将允许在没有 SCROLL
的情况下进行向后提取。但是,建议应用程序开发人员不要依赖于从未使用 SCROLL
创建的游标进行向后提取。如果指定了 NO SCROLL
,则在任何情况下都不允许向后提取。
当查询包含 FOR UPDATE
或 FOR SHARE
时,也不允许向后提取;因此,在这种情况下,不得指定 SCROLL
。
如果可滚动游标调用任何易失性函数(请参阅 第 36.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
语句;游标在声明时被认为是打开的。但是,ECPG,PostgreSQL 的嵌入式 SQL 预处理器,支持标准 SQL 游标约定,包括涉及 DECLARE
和 OPEN
语句的约定。
打开游标的底层服务器数据结构称为门户。门户名称在客户端协议中公开:客户端可以直接从打开的门户中获取行,如果它知道门户名称。使用 DECLARE
创建游标时,门户名称与游标名称相同。
您可以通过查询 pg_cursors
系统视图来查看所有可用的游标。
SQL 标准只允许在嵌入式中使用游标SQL和模块中。PostgreSQL 允许以交互方式使用游标。
根据 SQL 标准,通过 UPDATE ... WHERE CURRENT OF
和 DELETE ... WHERE CURRENT OF
语句对不敏感游标所做的更改在该同一游标中是可见的。PostgreSQL 将这些语句视为所有其他数据更改语句一样,它们在不敏感游标中是不可见的。
二进制游标是 PostgreSQL 的扩展。
如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步澄清的地方,请使用 此表单 报告文档问题。