文档 / SQL 状态码 / Class 26 SQL语句名称无效
26000 invalid_sql_statement_name
预备语句名称无效
ERROR 已实测 详解 实测通过
- 条件名
invalid_sql_statement_name- 宏名称
ERRCODE_INVALID_SQL_STATEMENT_NAMEERRCODE_UNDEFINED_PSTATEMENTERRCODE_UNDEFINED_PSTATEMENT- 启用版本
- 7.4
- 状态
- 活跃
版本覆盖
速览
26000 表示 PostgreSQL 被要求使用当前后端会话中不存在的命名预备语句。这是会话资源查找失败,先检查会话是否保持不变以及语句生命周期,再修改 SQL 文本。
含义
PREPARE 会在一个 PostgreSQL 会话中注册命名语句;EXECUTE 和 DEALLOCATE 也必须在同一会话按名称查找。连接池可能在两次操作之间换了后端。核心 prepare.c 路径使用 prepared statement "%s" does not exist,其中名称由服务器动态填入;固定的扩展查询路径还会在未命名语句不存在时使用 postgres.c 的 unnamed prepared statement does not exist。
诊断
先读取驱动异常中的 SQLSTATE 和主报文,并在 PREPARE、EXECUTE 周围记录后端 PID 或同等连接身份。在同一连接上查询 pg_prepared_statements,才能判断该失败会话是否存在这个名称;在另一个池连接上查询不能证明失败会话的状态。区分显式 DEALLOCATE、连接被替换和未命名语句路径,不要把它误判成 PREPARE 语法错误。
处理
如果命令位于显式事务中,先回滚失败块,再继续发命令。在真正执行它的会话上重新 PREPARE,并让应用或连接池在同一次 checkout 中完成定义和参数绑定。缺少语句本身没有执行预期操作,但重复更大的业务流程前仍应按业务请求标识和副作用检查执行正常校验。
可复现案例
在一次性实例上执行过的场景。其中 1 个附有可执行 SQL,正文相应小节里给出。
prepared_statement_recovery PG 10 / 18 有 SQL
前置条件
- A runner-owned disposable target is provisioned.
触发
Prepare a named statement, deallocate it, then execute the missing name on the same session.
断言
- SQLSTATE is 26000
- The prepared statement name is in the diagnostic
- The same session can recreate and execute the statement after the error
处置
Recreate the prepared statement on the session that will execute it; prepared statements are session-local.
清理
Drop the case schema with an owner connection.
报文
固定源码模板包括 prepare.c 的 prepared statement "%s" does not exist,以及扩展查询路径 postgres.c 的 unnamed prepared statement does not exist。选定案例记录的是 source_file = prepare.c、source_function = FetchPreparedStatement;只有命名模板带服务器端名称替换。应根据 SQLSTATE 和结构化诊断分支,不要把任一报文当成稳定完整字符串。
报文模板
源码里的格式串,不是某一次运行的输出。%s 之类是占位符,实际报文会填入对象名与取值。适用范围一栏是核验时留下的原始英文记录,未经翻译。
prepared statement "%s" does not exist
来源:src/backend/commands/prepare.c @ REL_18_6
适用范围:The unnamed prepared-statement path has a separate source template.
unnamed prepared statement does not exist
来源:src/backend/tcop/postgres.c @ REL_18_6
适用范围:This fixed protocol path has no server-side statement-name substitution.
代表案例
运行器从 verify/cases/26000/snippets.json(SHA-256 b9fdbb48371e0d9902cb9e055ececc4878c38422773a8a1571651d9952809032)读取下面的序列,并保证所有语句在同一连接执行;完整结果见公开案例导出和结构化证据。
PREPARE statement_name(integer) AS SELECT $1 + 1;
EXECUTE statement_name(1);
DEALLOCATE statement_name;
EXECUTE statement_name(1);
statement_name 是页面中的占位符。运行器会替换为唯一名称,释放它,断言 26000 和 IDLE,随后重复 registry 中同一组 PREPARE、EXECUTE、DEALLOCATE 三条语句修复会话。也就是说,恢复步骤是:在同一连接重新 PREPARE,执行它,并在 checkout 结束时 DEALLOCATE;引用的是现有 prepare、execute、deallocate registry 语句,而不是第二套 SQL 定义。
选定运行案例在 PostgreSQL 18.6 和 10.21 观察到 26000:先释放同名预备语句,再在同一会话执行它,得到带动态名称的诊断,连接保持 IDLE;随后重新 PREPARE 并成功执行。
版本
锁定目录从早期历史边界到当前正式快照都记录了该条件。18.6 固定源码同时包含命名和未命名预备语句路径;运行比较只覆盖 18.6 与 10.21 的命名路径。不同版本的源码行和报文措辞可以变化,选定目标中的 SQLSTATE 仍为 26000。
来源
- 上游源码 doc/src/sgml/ref/prepare.sgml
- 上游源码 src/backend/utils/errcodes.txt
- 上游源码 src/backend/tcop/postgres.c 第 1670–1672 行
- 上游源码 src/backend/commands/prepare.c 第 451–454 行
- 核验材料 raw/calls/REL_18_6.jsonl
证据
断言
每条断言都写明了是怎么核实的,以及它不覆盖什么。这一层是核验时留下的原始英文记录,照原样呈现,未经翻译。
-
26000 is the invalid_sql_statement_name condition in Class 26.
-
FetchPreparedStatement emits the source template prepared statement "%s" does not exist when a named prepared statement is absent.
-
The fixed postgres.c extended-query path emits unnamed prepared statement does not exist with SQLSTATE 26000 when the unnamed prepared statement is absent.
-
PREPARE creates a session-local named statement; DEALLOCATE removes it, so EXECUTE must run on the same backend where the statement was created.
-
The selected 26000 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 | prepared_statement_recovery |
| pg10 | 10.21 (Debian 10.21-1.pgdg90+1) | passed | prepared_statement_recovery |
同类 SQL 状态码
| 状态码 | 条件名 | 宏名称 | 严重等级 | 版本 |
|---|---|---|---|---|
| 26000 | invalid_sql_statement_name | ERRCODE_INVALID_SQL_STATEMENT_NAME |
ERROR | 7.4 |
| 会话中不存在该名称的预备语句。 | 活跃 | |||