跳转到主要内容

34000 — invalid_cursor_name(游标名称无效)

PostgreSQL SQLSTATE 34000:游标生命周期、会话归属与恢复。

34000 — invalid_cursor_name(游标名称无效)

速览

34000 表示当前后端会话无法解析游标或 portal 名称。已经关闭的游标、在另一个连接池会话声明的游标、或事务结束后消失的游标,都不是“游标存在但位置错误”(24000)。

字段
SQLSTATE 34000
条件名 invalid_cursor_name
状态 有效
已知存在于 7.4
锁定快照 9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3
ERRCODE_INVALID_CURSOR_NAME, ERRCODE_UNDEFINED_CURSOR
别名 ERRCODE_UNDEFINED_CURSOR

含义

执行器的 portal 路径在 FETCH 找不到命名 portal 时报告 cursor "%s" does not exist。游标属于后端会话;普通游标还受事务生命周期约束,除非明确声明合适的 hold 选项。因此连接池必须在预期事务边界内保持声明和使用都在同一连接。

诊断

记录 SQLSTATE、动态游标名称、后端 PID 和事务状态。检查应用是否提前 CLOSE、发生隐式提交、把连接归还池中,或已经换到另一会话。同一后端上的 pg_cursors 和会话身份可以帮助诊断;新连接不能查看或抓取旧连接拥有的游标。

处理

显式事务中的 FETCH 失败后,先回滚再发后续命令。在同一会话重新声明游标;如果工作必须跨连接池 checkout,就改为物化键或结果。只有确实需要提交后继续读取时才使用 holdable cursor;它不会让游标跨会话可用。

报文

选定核心路径使用 cursor "%s" does not exist;协议和 PL/pgSQL 路径可能使用 portal "%s" 或相同的 cursor 措辞。名称是动态值,应使用 SQLSTATE 和诊断字段,而不是跨版本、跨调用者比较完整报文。

代表案例

共享 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,但源码行和调用者措辞可能变化。

可对照24000 游标状态无效以及另一个会话资源错误26000 预备语句名称无效

来源

  • src.errcodes.18.6(SHA-256 6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba
  • src.portalcmds.18.6(SHA-256 e71c5bdb2da67771fb5f42f18b823e8af3ee6c31d5314e97a47ad18f7788bf35
  • DECLARE 官方文档 · 本地调用扫描 src.calls.REL_18_6(SHA-256 9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf