# 3F000 — 模式名称无效（invalid_schema_name）

> PostgreSQL SQLSTATE 3F000（模式名称无效，invalid_schema_name）的源码证据、诊断与处理参考。
---

# 3F000 — 模式名称无效

## 速览 {#at-a-glance}

SQLSTATE `3F000` 是 Class `3F` 中的 **invalid_schema_name**。`3F000` 表示已建立会话无法解析 schema 名称。选定的限定表路径得到 `schema "<generated>" does not exist`；固定的 namespace 和 schema 命令路径还覆盖对象创建等 SQL 阶段的解析，它不只是一个 `search_path` 提示。

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| 字段 | 值 |
| --- | --- |
| SQLSTATE | `3F000` |
| 条件名 | `invalid_schema_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_SCHEMA_NAME, ERRCODE_UNDEFINED_SCHEMA` |
| 别名 | `ERRCODE_UNDEFINED_SCHEMA` |

<!-- source facts: data/errcodes/3F000.json -->
<!-- END SQLSTATE FACTS -->

## 含义 {#meaning}

当 schema 名称本身无法解析时，namespace 查找会发出此条件。限定引用不存在的 schema 时使用 `schema "%s" does not exist`；未限定的 CREATE 没有可用创建命名空间时使用 `no schema has been selected to create in`。两者都是 schema 解析分支。普通未限定关系查找不到关系时使用 `42P01`，即使原因是 `search_path` 不合适；权限不足则进入 `42501`。

首先要判断失败的名称是 schema 还是关系。`missing_schema.repaired_table` 这样的限定引用会要求 namespace 代码解析准确的 schema，可以产生 `3F000`；没有显式 schema 的 CREATE 在没有可选创建 schema 时也可以产生 `3F000`。相反，`SELECT * FROM missing_table` 是未限定关系查找，通常产生 `42P01`；`search_path` 只决定搜索哪些关系，不会把该 SQLSTATE 变成 `3F000`。角色缺少所需权限时进入 `42501`。即使应用都报告“找不到 schema”，这些分支的修复也不同。

## 诊断 {#diagnosis}

区分明确缺失的 schema、没有选定创建 schema 的 CREATE、未限定关系查找，以及 42501 权限不足。选定自动提交会话在 ERROR 后保持 `IDLE`；所有者显式创建目标 schema 和表，插入一行，并在明确命名空间下核对。检查失败命令使用的相同角色和数据库。

使用失败命令的相同角色和数据库检查标识符，例如查看 `current_schemas(true)`，并确认目标 schema 能否在目录中解析。再核对命令是否限定名称：选定案例有意引用不存在的限定 schema；如果是未限定 CREATE，要检查 `search_path` 是否有可用创建目标；如果是未限定关系读取，关系缺失应归为 `42P01`，而不是 `3F000`。显式事务中的选定 `ERROR` 可能使事务进入 `INERROR`；自动提交的 `IDLE` 不是通用恢复结果。

## 处理 {#response}

使用迁移或所有者连接执行 `CREATE SCHEMA`，设置或限定目标命名空间，并用同一角色验证对象。对于 `no schema has been selected to create in`，应选择允许创建的 schema 或限定 CREATE；对于未限定的缺失关系，应修复关系名或目标 `search_path`，在关系可解析前应预期 `42P01`。不要通过添加无关 schema 到 `search_path` 掩盖命名空间错误；如果名称是有意删除的，应修复迁移或目标，而不是原样重试。

创建或暴露 schema 后，用同一角色重跑准确的限定语句，并核对最终对象。若失败语句位于显式事务中，应先回滚或回到预先设计的保存点，再执行无关 DDL。不要用扩大 schema 权限代替检查应用连接的数据库或使用的标识符。

## 实测诊断 {#messages}

固定的 namespace 路径在明确缺失 schema 时以 `ERROR` 发出主报文 `schema "%s" does not exist`，在未限定 CREATE 没有活动创建命名空间时发出 `no schema has been selected to create in`。选定的限定表案例没有固定 DETAIL 或 HINT。未限定关系查找不到时是独立的 `42P01` `relation "%s" does not exist` 路径，角色权限不足则是 `42501`。

选定的动态名称为 `c3f000_invalid_schema_name_missing`，错误发生在会话建立后，没有固定 DETAIL 或 HINT。这与源码确认的 schema 命令路径，以及启动阶段的客户端失败不同。

## 代表案例 {#case}

<!-- BEGIN SQLSTATE SNIPPET: invalid_schema_name -->

此 SQL 块限定不存在的 schema，创建 schema 与表，插入一行并核对，最后删除临时 schema。

```sql
CREATE TABLE missing_schema.repaired_table (id integer);
CREATE SCHEMA missing_schema;
CREATE TABLE missing_schema.repaired_table (id integer);
INSERT INTO missing_schema.repaired_table VALUES (1);
SELECT count(*) FROM missing_schema.repaired_table;
DROP SCHEMA missing_schema CASCADE;
```

<!-- END SQLSTATE SNIPPET -->

18.6 运行记录 SQLSTATE 为 `3F000`，主报文 `schema "c3f000_invalid_schema_name_missing" does not exist`；断言的错误后状态为 `IDLE`，随后探针/修复成功。18.6 与 10.21 的断言和清理均通过。

可下载的案例与证据投影分别是 [`3F000 案例 JSON`](../../data/cases/3f000.json) 和 [`作者证据`](../../data/evidence/3f000.json)。运行器清单为 `verify/cases/3F000/cases.json`；发布前会将页面 SQL 与共享注册表比对。

## 版本 {#versions}

上面的生成事实表记录锁定的目录快照和最早观察到的定义。本页自然运行范围是 PostgreSQL 18.6 与 10.21，不能据此推断所有中间版本的行为。

## 相关 {#related}

- [`3D000` — invalid_catalog_name](../3d000/)
- [`42501` — 相关条件](../42501/)

## 来源 {#sources}

- `src.namespace-missing-schema.18.6` — `src/backend/catalog/namespace.c` at `REL_18_6` commit `724edf9bde9d356724ad384a2e196edc3c9f80f7`; fixed blob SHA-256 `8c9e6a99e84fa2cec8a9b1de2ecbe3966a13f4ad68c6ccfbfb8134a754d73e56` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/catalog/namespace.c#L3545-L3547)).
- `src.namespace-missing-schema.10.23` — `src/backend/catalog/namespace.c` at `REL_10_23` commit `02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4`; fixed blob SHA-256 `74833354740d0e5679507d07b3c6e41aea01c2cb30adcd1e238bed3ebf96ddc6` ([source](https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/src/backend/catalog/namespace.c#L3022-L3024)).
- `src.namespace-creation-no-schema.10.23` — `src/backend/catalog/namespace.c` at `REL_10_23` commit `02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4`; fixed blob SHA-256 `74833354740d0e5679507d07b3c6e41aea01c2cb30adcd1e238bed3ebf96ddc6` ([source](https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/src/backend/catalog/namespace.c#L2967-L3004)).
- `src.parse-relation-undefined-table.10.23` — `src/backend/parser/parse_relation.c` at `REL_10_23` commit `02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4`; fixed blob SHA-256 `a34f40fc93fa5df0015fe5af5ee7761ccba2d16a791cda69ae07848ed27616b5` ([source](https://github.com/postgres/postgres/blob/02991e79f8f58bc208f05dcc8af0c62dbe0a6ea4/src/backend/parser/parse_relation.c#L1147-L1184)).
- `src.calls.REL_18_6` / `src.calls.REL_10_23` — fixed local call scans, SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf` / `00d16d3eb01b71ccf1b245c8f3102f9d0ec9f36fb02777b8dd1b99fcb263040c`; these scans preserve the resolved call context used by the claims.
