选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

百科 / 错误代码 / Class 24 游标状态无效

24000 invalid_cursor_state

游标状态无效

ERROR 已实测 参考 实测通过

类别
Class 24 游标状态无效
严重等级
ERROR
条件名
invalid_cursor_state
宏名称
ERRCODE_INVALID_CURSOR_STATE
启用版本
7.4
状态
活跃

版本覆盖

速览

24000 表示游标或 portal 状态不满足当前操作。本案例声明了有效游标,却在 FETCH 定位前执行 WHERE CURRENT OF,因而报“游标未定位到行”。

含义

WHERE CURRENT OF 要求游标来自可更新查询,并已通过 FETCH 选中当前行;声明本身不会定位。其他非 SELECT、已保持、不可更新或缺少 FOR UPDATE/SHARE 引用的游标也有不同 24000 模板。

诊断

记录游标名和操作,检查声明、事务生命周期、FETCH 方向及可更新性。显式事务错误后本案例为 INERROR,回滚后回到 IDLE;本案例用主键直接更新修复,未测试重新 DECLARE/FETCH。

处理

先 FETCH 定位再使用 CURRENT OF,或者使用确定性的键更新。保持游标和事务生命周期显式,失败事务先回滚。

可复现案例

在一次性实例上执行过的场景。其中 1 个附有可执行 SQL,正文相应小节里给出。

current_of_before_fetch PG 10 / 18 有 SQL

前置条件

  • A cursor is declared for a SELECT ... FOR UPDATE
  • The cursor has not fetched a row

触发

Use WHERE CURRENT OF before the cursor is positioned on a row.

断言

  • SQLSTATE is 24000
  • The connection recovers after rollback
  • A direct update succeeds afterward

处置

Fetch or otherwise position the cursor before CURRENT OF, or use a key-based update whose concurrency semantics are explicit.

清理

Drop the case schema with an owner connection.

实测诊断

18.6 (Homebrew) / latest:SQLSTATE 24000;primary cursor "item_cursor" is not positioned on a row;after_error INERROR;after_rollback IDLE10.21 (Debian 10.21-1.pgdg90+1) / pg10:SQLSTATE 24000;primary cursor "item_cursor" is not positioned on a row;after_error INERROR;after_rollback IDLE

报文模板

源码里的格式串,不是某一次运行的输出。%s 之类是占位符,实际报文会填入对象名与取值。适用范围一栏是核验时留下的原始英文记录,未经翻译。

主消息 cursor "%s" is not positioned on a row

来源:src/backend/executor/execCurrent.c @ REL_18_6

适用范围:The same template is also used by another CURRENT OF path; the cursor name is substituted at runtime.

代表案例

运行器从 verify/cases/24000/snippets.json(SHA-256 cafca57825378362df0527384614bf658bf86cd3101e1eb520ea0641819f2789)读取下列片段,并为临时 schema 替换表名;完整 setup、断言与清理见 案例导出

-- create
CREATE TABLE items(id integer PRIMARY KEY, note text NOT NULL);
-- seed
INSERT INTO items VALUES (1, 'seed');
-- begin
BEGIN;
-- declare
DECLARE item_cursor CURSOR FOR SELECT id FROM items FOR UPDATE;
-- trigger
UPDATE items SET note = 'bad' WHERE CURRENT OF item_cursor;
-- rollback
ROLLBACK;
-- repair
UPDATE items SET note = 'repaired' WHERE id = 1;
-- verify
SELECT id, note FROM items;

本案例对应的 SQLSTATE、诊断、事务状态和修复断言均来自上述共享 registry;结构化证据 · 案例导出

作者证据 ID:identity, current-of, runtime。选定运行记录:runtime.24000-batch1-latest2-20260909.latest, runtime.24000-batch1-pg10-20260909.pg10

版本与边界

锁定目录在 7.4 已观察到该条件,并在列出的正式快照中均存在。选定运行覆盖 18.6 与 10.21 的 FETCH 前 CURRENT OF 路径;其他游标状态需要独立案例。

来源

证据

断言

每条断言都写明了是怎么核实的,以及它不覆盖什么。这一层是核验时留下的原始英文记录,照原样呈现,未经翻译。

  • 24000 is invalid_cursor_state in Class 24.

    核实方式Read the fixed condition row.

    不覆盖The class has several cursor/portal states; the observed message is one path.

    来源src/backend/utils/errcodes.txt

  • UPDATE or DELETE ... WHERE CURRENT OF requires a positioned, updatable cursor row; before FETCH the executor reports 24000.

    核实方式Trace execCurrent and the documented DECLARE/CURRENT OF rules.

    不覆盖A cursor can be validly declared yet still be unpositioned; declaration alone does not make CURRENT OF usable.

    来源src/backend/executor/execCurrent.c · doc/src/sgml/ref/declare.sgml · doc/src/sgml/ref/update.sgml · raw/calls/REL_18_6.jsonl

  • The selected explicit transaction case returned 24000 before FETCH, entered INERROR, recovered after ROLLBACK, and then directly repaired the row on PG18.6 and PG10.21.

    核实方式Read the selected summaries and raw diagnostics.

    不覆盖Only the before-FETCH CURRENT OF path was run; other cursor states use other source templates.

运行记录

目标服务器版本结果覆盖案例
latest 18.6 (Homebrew) passed current_of_before_fetch
pg10 10.21 (Debian 10.21-1.pgdg90+1) passed current_of_before_fetch