跳转到主要内容

23001 — RESTRICT 约束冲突(restrict_violation)

PostgreSQL SQLSTATE 23001:RESTRICT 约束冲突的来源与诊断参考。

23001 — RESTRICT 约束冲突

速览

23001 是立即执行的外键 RESTRICT 动作导致的专用冲突。18.6 案例删除仍被引用的父行时返回该码;10.21 对同一操作返回 23503,必须记录版本和完整诊断。另一个 PostgreSQL 17.11 对照案例对该 RESTRICT 操作也返回 23503,不计作 23001 覆盖。

字段
SQLSTATE 23001
条件名 restrict_violation
状态 有效
已知存在于 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_RESTRICT_VIOLATION
别名

含义

ON DELETE/UPDATE RESTRICT 会立即检查引用行,且不能延迟;可延迟的 NO ACTION 则可以把检查推迟到相应提交点。源码根据父表、外键、子表和可见键值动态组装报文。

诊断

记录精确 SQLSTATE、constraint_name、表名和 DETAIL,先检查子表。显式事务删除失败后连接为 INERROR,必须 ROLLBACK,再在新的 BEGIN/COMMIT 中删除子行和父行。

处理

按完整性语义选择删除/改派依赖行、放弃父操作或重新设计 FK 动作。不要为了迁移方便把 RESTRICT 偷换成可延迟 NO ACTION。

实测诊断

18.6 (Homebrew) / latest:SQLSTATE 23001;primary update or delete on table "parents" violates RESTRICT setting of foreign key constraint "children_parent_id_fkey" on table "children";DETAIL Key (id)=(1) is referenced from table "children".;after_error INERROR;after_rollback IDLE10.21 (Debian 10.21-1.pgdg90+1) / pg10:SQLSTATE 23503;primary update or delete on table "parents" violates foreign key constraint "children_parent_id_fkey" on table "children";DETAIL Key (id)=(1) is still referenced from table "children".;after_error INERROR;after_rollback IDLE17.11 (pg17) / boundary:SQLSTATE 23503;primary update or delete on table "parents" violates foreign key constraint "children_parent_id_fkey" on table "children";DETAIL Key (id)=(1) is still referenced from table "children".;after_error INERROR;after_rollback IDLE;最终计数 [0, 0]。该边界案例不计作 23001 覆盖。

代表案例

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

-- create_parent
CREATE TABLE parents(id integer PRIMARY KEY);
-- create_child
CREATE TABLE children(id integer PRIMARY KEY, parent_id integer NOT NULL REFERENCES parents(id) ON DELETE RESTRICT);
-- seed_parent
INSERT INTO parents VALUES (1);
-- seed_child
INSERT INTO children VALUES (10, 1);
-- begin
BEGIN;
-- trigger
DELETE FROM parents WHERE id = 1;
-- rollback
ROLLBACK;
-- repair_begin
BEGIN;
-- repair_child
DELETE FROM children WHERE id = 10;
-- repair_parent
DELETE FROM parents WHERE id = 1;
-- commit
COMMIT;
-- verify
SELECT (SELECT count(*) FROM parents), (SELECT count(*) FROM children);

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

作者证据 ID:identityrestrict-pathno-action-boundaryruntimeruntime.pg17-boundary。选定基础运行记录:runtime.23001-batch1-latest2-20260909.latestruntime.23001-batch1-pg10b-20260909.pg10。单独的边界记录:runtime.23001-boundary-pg17-final-20260909.pg17

版本与边界

锁定目录在 7.4 已观察到该条件,并在列出的正式快照中均存在。选定基础案例在 18.6 观察到 23001,在 10.21 对同一 RESTRICT 删除观察到 23503。另一个 PG17.11 边界对照也返回 23503,并保持 INERRORIDLE 的恢复边界;该记录单独保留,不能推广为所有 PostgreSQL 11–17 小版本的普遍结果。

对比 23503 外键冲突23505 唯一约束冲突23514 CHECK 冲突

来源

  • src.errcodes.18.6 (SHA-256 6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba)
  • src.calls.REL_18_6 (SHA-256 9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf)
  • src.ri_triggers.18.6 (SHA-256 a3fed49fbda88fe0fe5bcf35eb019fced28596ae4046233f2acb2eb9f90ab1da)
  • doc.ddl-constraints.18.6 (SHA-256 ce1919d9236f2e71672660e1a347146472e966e4d19b77fde5ae345dd1db6ec7) · 官方文档