百科 / 错误代码 / Class 34 游标名称无效
34000 invalid_cursor_name
游标名称无效
ERROR 已实测 详解 实测通过
- 条件名
invalid_cursor_name- 宏名称
ERRCODE_INVALID_CURSOR_NAMEERRCODE_UNDEFINED_CURSORERRCODE_UNDEFINED_CURSOR- 启用版本
- 7.4
- 状态
- 活跃
版本覆盖
速览
34000 表示当前后端会话无法解析游标或 portal 名称。已经关闭的游标、在另一个连接池会话声明的游标、或事务结束后消失的游标,都不是“游标存在但位置错误”(24000)。
含义
执行器的 portal 路径在 FETCH 找不到命名 portal 时报告 cursor "%s" does not exist。游标属于后端会话;普通游标还受事务生命周期约束,除非明确声明合适的 hold 选项。因此连接池必须在预期事务边界内保持声明和使用都在同一连接。
诊断
记录 SQLSTATE、动态游标名称、后端 PID 和事务状态。检查应用是否提前 CLOSE、发生隐式提交、把连接归还池中,或已经换到另一会话。同一后端上的 pg_cursors 和会话身份可以帮助诊断;新连接不能查看或抓取旧连接拥有的游标。
处理
显式事务中的 FETCH 失败后,先回滚再发后续命令。在同一会话重新声明游标;如果工作必须跨连接池 checkout,就改为物化键或结果。只有确实需要提交后继续读取时才使用 holdable cursor;它不会让游标跨会话可用。
可复现案例
在一次性实例上执行过的场景。其中 1 个附有可执行 SQL,正文相应小节里给出。
cursor_lifecycle_recovery PG 10 / 18 有 SQL
前置条件
- A runner-owned disposable target is provisioned.
触发
Declare and close a named cursor, attempt to use it again, then recreate it in a new explicit transaction on the same session.
断言
- SQLSTATE is 34000
- The missing cursor diagnostic is preserved
- The failed block recovers through ROLLBACK
- A recreated cursor can FETCH and COMMIT
处置
Keep cursor use on the declaring backend session and respect its transaction lifetime; after an error, roll back before recreating it.
清理
Drop the case schema with an owner connection.
报文
选定核心路径使用 cursor "%s" does not exist;协议和 PL/pgSQL 路径可能使用 portal "%s" 或相同的 cursor 措辞。名称是动态值,应使用 SQLSTATE 和诊断字段,而不是跨版本、跨调用者比较完整报文。
报文模板
源码里的格式串,不是某一次运行的输出。%s 之类是占位符,实际报文会填入对象名与取值。适用范围一栏是核验时留下的原始英文记录,未经翻译。
cursor "%s" does not exist
来源:src/backend/commands/portalcmds.c @ REL_18_6
适用范围:The portal protocol path uses portal "%s" does not exist.
代表案例
共享 registry verify/cases/34000/snippets.json(SHA-256 ad5b519e8ca30fd2636b1d0bace32dc18558cccc7b9d360081c27b12a1405f08)先声明并关闭游标,验证缺失 FETCH,再在同一会话回滚并重新声明。见公开案例导出和结构化证据。
BEGIN;
DECLARE cursor_name CURSOR FOR SELECT 1;
CLOSE cursor_name;
FETCH cursor_name;
ROLLBACK;
BEGIN;
DECLARE cursor_name CURSOR FOR SELECT 1;
FETCH cursor_name;
CLOSE cursor_name;
COMMIT;
运行器会替换唯一游标名。第一次 FETCH 特意放在 CLOSE 之后;第二次在新的 BEGIN 和声明之后执行,成功返回数据,证明是生命周期修复而非客户端模拟。
选定案例在 PostgreSQL 18.6 和 10.21 关闭命名游标后执行 FETCH,观察到 34000。失败块进入 INERROR;回滚后重新声明、抓取、关闭并提交,连接回到 IDLE。
版本
锁定目录在正式快照中都记录了该条件。18.6 和 10.23 源码扫描都包含 portal、PL/pgSQL 路径;选定运行在 18.6 与 10.21 观察到相同 SQLSTATE,但源码行和调用者措辞可能变化。
来源
- 上游源码 doc/src/sgml/ref/declare.sgml
- 上游源码 src/backend/utils/errcodes.txt
- 上游源码 src/backend/commands/portalcmds.c 第 197–199 行
- 核验材料 raw/calls/REL_18_6.jsonl
证据
断言
每条断言都写明了是怎么核实的,以及它不覆盖什么。这一层是核验时留下的原始英文记录,照原样呈现,未经翻译。
-
34000 is the invalid_cursor_name condition in Class 34 and shares the undefined-cursor alias.
-
PerformPortalFetch emits cursor "%s" does not exist when the named portal is absent.
-
A named cursor belongs to its backend session and transaction lifecycle; closing it or losing its transaction makes a later FETCH invalid.
-
The selected 34000 case passed on PostgreSQL 18.6 and 10.21 with the structured SQLSTATE, transaction-state, and repair assertions recorded in the runtime entries.
运行记录
| 目标 | 服务器版本 | 结果 | 覆盖案例 |
|---|---|---|---|
| latest | 18.6 (Homebrew) | passed | cursor_lifecycle_recovery |
| pg10 | 10.21 (Debian 10.21-1.pgdg90+1) | passed | cursor_lifecycle_recovery |