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

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

百科 / 错误代码 / Class 42 语法错误或访问规则冲突

42830 invalid_foreign_key

无效外键

ERROR 已实测 参考 实测通过

条件名
invalid_foreign_key
宏名称
ERRCODE_INVALID_FOREIGN_KEY
启用版本
7.4
状态
活跃

版本覆盖

速览

42830invalid_foreign_key(无效外键):外键定义在被引用列上找不到合格唯一键。本案例的父表整数列没有唯一约束。

含义

创建时先检查父键,尚未插入子行。固定主报文为 there is no unique constraint matching given keys for referenced table "%s"。普通 FK 的被引用列集合可以匹配物理顺序不同但合格的唯一索引;源码匹配器会拒绝被引用列重复,并要求列数正确、唯一、有效且没有部分谓词或索引表达式。若匹配到可延迟的唯一/主键索引,则进入仅源码确认的 55000 分支。这是定义时错误,不同于 23503;自动提交 ALTER 失败后为 IDLE

诊断

将被引用列集合与 pg_constraintpg_index 对照。检查重复引用、列数、唯一/主键属性、有效性、部分谓词和表达式;普通路径不要求物理索引顺序与 FK 列表相同。还要检查 indimmediate:匹配但可延迟的键会报 55000,不是本案例的 42830。类型相同本身不能使键符合要求。

处理

在被引用列集合上添加或使用有意且不可延迟的唯一键,再创建 FK。核对父表键的业务含义及 NULL/MATCH 语义;过宽唯一约束可能改变可接受数据。不要为了匹配 FK 书写顺序而重排本来合格的索引,也不要把部分或表达式索引当作合格键。案例添加 UNIQUE (id) 后创建 FK。显式事务中被拒绝的 ALTER TABLE 会使事务进入 INERROR,应先回滚或回到合适的 savepoint 再重试;本案例的自动提交路径回到 IDLE

可复现案例

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

fk_missing_unique_key PG 10 / 18 有 SQL

前置条件

  • A runner-owned disposable target is provisioned.

触发

Create a foreign key referencing a parent column with no unique constraint.

断言

  • SQLSTATE is 42830 with the missing referenced unique-key message
  • The failed autocommit session remains IDLE
  • Adding a parent UNIQUE constraint then the FK creates one valid constraint

处置

Add a deliberate primary/unique key over the referenced columns before defining the FK; matching types alone are insufficient.

清理

Drop the runner schema and both tables.

实测诊断

选定 tablecmds.c 组是 ERROR,主报文为 there is no unique constraint matching given keys for referenced table "%s",没有 DETAIL/HINT。同一匹配器还有仅源码确认的 55000object_not_in_prerequisite_state)变体:当唯一键本来匹配但可延迟时为 cannot use a deferrable unique constraint for referenced table "%s"

报文模板

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

主消息 there is no unique constraint matching given keys for referenced table "%s"

来源:src/backend/commands/tablecmds.c @ REL_18_6 · src/backend/commands/tablecmds.c @ REL_10_23

主消息 cannot use a deferrable unique constraint for referenced table "%s"

来源:src/backend/commands/tablecmds.c @ REL_18_6 · src/backend/commands/tablecmds.c @ REL_10_23

代表案例

注册表创建父子表,先尝试 FK,再添加父唯一键、创建有效 FK 并统计。

CREATE TABLE syntax_schema.fk_parent (id integer);
CREATE TABLE syntax_schema.fk_child (parent_id integer);
ALTER TABLE syntax_schema.fk_child ADD CONSTRAINT fk_bad FOREIGN KEY (parent_id) REFERENCES syntax_schema.fk_parent (id);
ALTER TABLE syntax_schema.fk_parent ADD CONSTRAINT fk_parent_id_key UNIQUE (id);
ALTER TABLE syntax_schema.fk_child ADD CONSTRAINT fk_good FOREIGN KEY (parent_id) REFERENCES syntax_schema.fk_parent (id);
SELECT count(*) FROM pg_constraint c JOIN pg_namespace n ON n.oid = c.connamespace WHERE n.nspname = 'syntax_schema_name' AND c.conname = 'fk_good' AND c.contype = 'f';

选定的 18.6 与 10.21 运行均通过 SQLSTATE、严重级别、状态/恢复、修复、清理和一次性实例停止断言。详见 案例 JSON作者证据;私有清单和注册表哈希也记录在其中。

版本

锁定目录从 7.4 存在边界起包含该条件并列出相关快照。选定自然案例已在 PostgreSQL 18.6 与 10.21 通过;这是有界观察,不能推断所有中间版本或所有源码分支。

来源

证据

断言

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

  • 42830 is the invalid_foreign_key condition in Class 42.

    核实方式Read fixed errcodes.txt and locked catalogue metadata.

    不覆盖Identity does not identify every backend call that can reuse this SQLSTATE.

    来源src/backend/utils/errcodes.txt

  • The selected fk_missing_unique_key follows a resolved PostgreSQL source-call group; the complete matcher accepts a duplicate-free referenced column set in any physical order only when the candidate index has the required count, uniqueness, validity, and no predicate or expressions.

    核实方式Trace the REL_18_6 and REL_10_23 source-call records at the locked commits.

    不覆盖This is one mechanism boundary, not an exhaustive inventory of the code.

    来源src/backend/commands/tablecmds.c · src/backend/commands/tablecmds.c · src/backend/commands/tablecmds.c · src/backend/commands/tablecmds.c

  • The same matcher rejects a duplicate referenced-column list with 42830 and rejects an otherwise matching deferrable unique or primary index with OBJECT_NOT_IN_PREREQUISITE_STATE (55000); the latter is source-only in this review.

    核实方式Read the complete transformFkeyCheckAttrs function in both locked tablecmds.c snapshots.

    不覆盖The selected runtime covers only the missing-key 42830 case and does not observe the duplicate-list or deferrable branches.

    来源src/backend/commands/tablecmds.c · src/backend/commands/tablecmds.c

  • The selected fk_missing_unique_key passed on isolated PostgreSQL 18.6 and 10.21 targets.

    核实方式Run the shared SQL registry and inspect SQLSTATE, severity, state, repair, cleanup, and target stop.

    不覆盖Scope is limited to these statements, psycopg, and two versions.

    来源verify/cases/42830/cases.json · verify/cases/42830/snippets.json

  • The locked catalogue records 42830 from the 7.4 presence bound through the listed snapshots; runtime scope is 18.6 and 10.21.

    核实方式Read generated facts, fixed calls, and selected summaries.

    不覆盖Definition presence is not an exact behavioral introduction; two runtime versions do not prove every intermediate behavior.

    来源src/backend/utils/errcodes.txt · raw/calls/REL_18_6.jsonl · raw/calls/REL_10_23.jsonl

运行记录

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

同类错误代码

Class 42 语法错误或访问规则冲突 下的其他成员。