跳转到主要内容

42P01 — undefined_table:未定义的表或关系

当引用的关系无法解析时,PostgreSQL 会报告 SQLSTATE 42P01。应检查模式限定、search_path、标识符引用和迁移,再决定是否创建或重命名对象。

速览

42P01 是 PostgreSQL 类别 42 syntax_error_or_access_rule_violation 中的 undefined_table 条件。这个名称沿袭已久;无法解析的引用可以是表、视图、物化视图、外部表或其他关系名称。

普通诊断是未限定引用的 relation "%s" does not exist,或限定引用的 relation "%s.%s" does not exist。解析器在查询执行前报告 SQLSTATE;自动提交连接不会因为这个查询错误留下失败事务。

代表性案例查询不存在的模式限定关系,再创建有效关系并读取它。PostgreSQL 18.6 和隔离的 PostgreSQL 10.21 目标均返回 42P01,连接保持 IDLE,修正后的查询成功。run ID 和断言见公开证据 JSON

字段
SQLSTATE 42P01
条件名 undefined_table
状态 有效
已知存在于 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_UNDEFINED_TABLE
别名

含义与触发路径

解析阶段会根据当前命名空间和 search_path 解析每个关系。如果限定名称不存在,parse_relation.c 产生两部分名称报文;如果未限定名称不存在,则产生一部分名称报文。拼写错误、迁移尚未执行、连接了错误数据库、search_path 不同,或者带引号标识符大小写不一致,都可能产生这个 SQLSTATE。

这是名称解析错误,不等于物理表一定被删除。关系可能存在于另一个模式或数据库中,角色也可能缺少查看或使用它所需的权限。反过来,按猜测的名称创建表会掩盖部署或引用错误。

解析器还会在某些无效 FROM 项引用和 CTE 前向引用中使用 42P01,但 detail 或 hint 可能不同。应结合完整报文和上下文,将这些形式与缺少关系区分开。

报文与诊断

runner 的操作先限定模式查询,再查询修正后的关系。隔离 harness 提供临时模式;查询形状如下:

SELECT * FROM does_not_exist;
CREATE TABLE exists(id integer PRIMARY KEY);
SELECT count(*) FROM exists;

PostgreSQL 18.6 返回:

SQLSTATE: 42P01
severity: ERROR
message_primary: relation "c42p01_missing_relation.does_not_exist" does not exist
source: parse_relation.c / parserOpenTable / line 1480

PG10 目标返回相同的主报文,对应源码行号为 1159。限定形式会在报文中保留模式和关系名称。未限定引用使用固定源码模板 relation "%s" does not exist;CTE 前向引用或无效 FROM 引用可能附带 detail 或 hint。

诊断

记录 SQLSTATE、主报文、detail、hint、语句位置、当前数据库、角色和 search_path。检查应用使用的准确拼写与引用方式。通过有权限的管理连接查询 pg_class/pg_namespace 或使用 to_regclass(),确认关系实际存在的位置。

对照已部署迁移版本、连接数据库和模式。连接池中的 session 可能带有不同于建表连接的 search_path。如果对象预期是临时对象,应确认查询仍在创建它的同一个 session 中执行。

代表性错误发生在自动提交下,连接保持 IDLE;修正后的查询返回 count 0 并仍为 IDLE。如果缺少关系的引用发生在显式事务中,事务仍可能进入 INERROR,因此应记录实际状态,不要假定所有 42P01 都不会影响周围工作。

处理与修复

按部署和应用配置修复名称解析原因:

  • 明确选择目标模式,或为 session 设置并验证 search_path
  • 在提供查询前于正确数据库执行缺少的迁移。
  • 对大小写敏感的标识符保留准确的双引号;检查依赖后再按统一约定重命名。
  • 只有在缺少对象是预期分支时才使用 to_regclass() 等预检;意外部署失败不应静默创建替代关系。

修正关系后重新执行原查询,并验证返回值和事务状态。成功执行 CREATE TABLE 或打开新连接,都不能证明所有应用 session 解析到同一个对象。

版本与边界

目录在 PostgreSQL 7.4 的锁定定义中已观察到 42P01,并持续到 8.4.22 的 pre-9.0 定义;随后在列出的所有正式快照直到 PostgreSQL 18.6 以及 PostgreSQL 19 Beta 3 预览中存在。这是 definition_only 的存在边界,不是确切实现引入版本或运行时使用断言。扫描范围内没有记录该条件的定义变化。

缺少关系案例在 PostgreSQL 18.6 和 10.21 上均通过。源码行号和解析器 hint 会因版本及引用形式变化。本页覆盖模式限定的缺少关系和有效后续查询,不覆盖所有使用 42P01 的命名空间或访问规则路径。

42P02undefined_parameter 处理缺少查询参数。3F000invalid_schema_name 处理无效模式名称。42501insufficient_privilege 是名称解析之后的访问失败。57014query_canceled 可能中断修复查询,但原因不同。

来源

结构化证据记录在公开证据 JSON中。源码记录固定到 PostgreSQL commit 724edf9bde9d356724ad384a2e196edc3c9f80f7;运行记录保留两个目标 ID 和结构化观察。