百科 / 错误代码 / Class 23 完整性约束冲突
23001 restrict_violation
RESTRICT 约束冲突
ERROR 已实测 详解 实测通过
- 条件名
restrict_violation- 宏名称
ERRCODE_RESTRICT_VIOLATION- 启用版本
- 7.4
- 状态
- 活跃
版本覆盖
速览
23001 是立即执行的外键 RESTRICT 动作导致的专用冲突。18.6 案例删除仍被引用的父行时返回该码;10.21 对同一操作返回 23503,必须记录版本和完整诊断。另一个 PostgreSQL 17.11 对照案例对该 RESTRICT 操作也返回 23503,不计作 23001 覆盖。
含义
ON DELETE/UPDATE RESTRICT 会立即检查引用行,且不能延迟;可延迟的 NO ACTION 则可以把检查推迟到相应提交点。源码根据父表、外键、子表和可见键值动态组装报文。
诊断
记录精确 SQLSTATE、constraint_name、表名和 DETAIL,先检查子表。显式事务删除失败后连接为 INERROR,必须 ROLLBACK,再在新的 BEGIN/COMMIT 中删除子行和父行。
处理
按完整性语义选择删除/改派依赖行、放弃父操作或重新设计 FK 动作。不要为了迁移方便把 RESTRICT 偷换成可延迟 NO ACTION。
可复现案例
在一次性实例上执行过的场景。其中 1 个附有可执行 SQL,正文相应小节里给出。
restrict_delete_referenced_parent PG 18 有 SQL
前置条件
- A child row references a parent through ON DELETE RESTRICT
- The parent delete is attempted while the child remains
触发
Delete the referenced parent row.
断言
- SQLSTATE is 23001
- The RESTRICT constraint and referencing table are identified
- Deleting the child first permits an explicit parent repair
处置
Resolve the dependent row according to business rules, then delete or retain the parent; changing RESTRICT to another action is a schema decision, not an error fix.
清理
Drop the case schema with an owner connection.
实测诊断
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 IDLE。
10.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 IDLE。
17.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 覆盖。
报文模板
源码里的格式串,不是某一次运行的输出。%s 之类是占位符,实际报文会填入对象名与取值。适用范围一栏是核验时留下的原始英文记录,未经翻译。
update or delete on table "%s" violates RESTRICT setting of foreign key constraint "%s" on table "%s"
Key (%s)=(%s) is referenced from table "%s".
来源:src/backend/utils/adt/ri_triggers.c @ REL_18_6
适用范围:The privilege-aware branch can instead emit the source detail template without key values.
代表案例
运行器从 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:identity、restrict-path、no-action-boundary、runtime、runtime.pg17-boundary。选定基础运行记录:runtime.23001-batch1-latest2-20260909.latest、runtime.23001-batch1-pg10b-20260909.pg10。单独的边界记录:runtime.23001-boundary-pg17-final-20260909.pg17。
版本与边界
锁定目录在 7.4 已观察到该条件,并在列出的正式快照中均存在。选定基础案例在 18.6 观察到 23001,在 10.21 对同一 RESTRICT 删除观察到 23503。另一个 PG17.11 边界对照也返回 23503,并保持 INERROR 到 IDLE 的恢复边界;该记录单独保留,不能推广为所有 PostgreSQL 11–17 小版本的普遍结果。
来源
- 上游源码 doc/src/sgml/ddl.sgml
- 上游源码 src/backend/utils/errcodes.txt
- 上游源码 src/backend/utils/adt/ri_triggers.c 第 2785–2797 行
- 核验材料 raw/calls/REL_18_6.jsonl
证据
断言
每条断言都写明了是怎么核实的,以及它不覆盖什么。这一层是核验时留下的原始英文记录,照原样呈现,未经翻译。
-
23001 is restrict_violation, a specific Class 23 condition.
-
The RI trigger reports 23001 when an immediate ON DELETE or ON UPDATE RESTRICT action finds a referencing row.
-
RESTRICT is checked immediately and is not deferrable; NO ACTION can be deferred when the constraint is declared DEFERRABLE, and PostgreSQL 10 uses the general 23503 path for the tested RESTRICT delete.
-
The selected PG18 run returned 23001, entered INERROR, recovered after ROLLBACK, and committed deletion after removing the dependent row; PG10 returned 23503 for the same mechanism.
-
On the fixed PG17.11 boundary case, the same referenced-parent ON DELETE RESTRICT operation returned the general foreign_key_violation 23503 rather than dedicated 23001; the failed transaction moved from INERROR to IDLE after ROLLBACK and cleanup assertions passed.
运行记录
| 目标 | 服务器版本 | 结果 | 覆盖案例 |
|---|---|---|---|
| latest | 18.6 (Homebrew) | passed | restrict_delete_referenced_parent |
| pg10 | 10.21 (Debian 10.21-1.pgdg90+1) | not_applicable | restrict_delete_referenced_parent |
| pg17 | 17.11 (Debian 17.11-1.pgdg13+2) | not_applicable | restrict_delete_referenced_parent |
同类错误代码
Class 23 完整性约束冲突 下的其他成员。