# 23001 — RESTRICT 约束冲突（restrict_violation）

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

# 23001 — RESTRICT 约束冲突

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

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

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

| 字段 | 值 |
| --- | --- |
| 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` |
| 别名 | `—` |

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

## 含义 {#meaning}

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

## 诊断 {#diagnosis}

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

## 处理 {#response}

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

## 实测诊断 {#messages}

`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 覆盖。

## 代表案例 {#case}

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

<!-- BEGIN SQLSTATE SNIPPET: restrict_delete_referenced_parent -->
```sql
-- 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);
```
<!-- END SQLSTATE SNIPPET -->

本案例对应的 SQLSTATE、诊断、事务状态和修复断言均来自上述共享 registry；[结构化证据](../../data/evidence/23001.json) · [案例导出](../../data/cases/23001.json)。

作者证据 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`。

## 版本与边界 {#versions}

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

## 相关 {#related}

对比 [23503 外键冲突](../23503/)、[23505 唯一约束冲突](../23505/) 和 [23514 CHECK 冲突](../23514/)。

## 来源 {#sources}

- [`src.errcodes.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt) (SHA-256 `6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba`)
- `src.calls.REL_18_6` (SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf`)
- [`src.ri_triggers.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/ri_triggers.c#L2785-L2797) (SHA-256 `a3fed49fbda88fe0fe5bcf35eb019fced28596ae4046233f2acb2eb9f90ab1da`)
- [`doc.ddl-constraints.18.6`](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/doc/src/sgml/ddl.sgml) (SHA-256 `ce1919d9236f2e71672660e1a347146472e966e4d19b77fde5ae345dd1db6ec7`) · [官方文档](https://www.postgresql.org/docs/18/ddl-constraints.html#DDL-CONSTRAINTS-FK)
