【问题标题】:Update or Delete Violates foreign key constraint更新或删除违反外键约束
【发布时间】:2025-12-09 02:25:01
【问题描述】:

我有两个如下所示的表。

CREATE TABLE book (
    book_id BIGSERIAL PRIMARY KEY,
    book_special_id character(10) NOT NULL DEFAULT random_string(10) UNIQUE,
    author_id bigint REFERENCES author(author_id) ON DELETE RESTRICT,
    category_id bigint REFERENCES category(category_id) ON DELETE RESTRICT,
    title text NOT NULL,
    subtitle text,
    book_text text
);

CREATE TABLE booksubcategory (
    booksubcategory_id BIGSERIAL PRIMARY KEY,
    book_id BIGSERIAL REFERENCES book(book_id) ON DELETE CASCADE,
    subcategory_id BIGSERIAL REFERENCES subcategory(subcategory_id) ON DELETE RESTRICT,
    CONSTRAINT booksubcategory_book_id_subcategory_id_key UNIQUE (book_id, subcategory_id)
);

在此示例中,book_id 列是 book 表中的主键,并且是 booksubcategory 表中的引用外键。当我尝试运行以下 sql 时,我收到错误:

ERROR: update or delete on table "book" violates foreign key constraint "booksubcategory_book_id_fkey" on table "booksubcategory"
Detail: Key (book_id)=(888392) is still referenced from table "booksubcategory"

这是 SQL 的样子。

INSERT INTO book (book_special_id, author_id, category_id, title, subtitle, book_text) 
VALUES ("D4jOko2IP0",34, 4, "Book Example", "Book Subtitle", "Some lengthy text") 
ON CONFLICT (book_special_id) 
DO UPDATE SET author_id=EXCLUDED.author_id, book_id=EXCLUDED.book_id,  category_id=EXCLUDED.category_id, title=EXCLUDED.title, subtitle=EXCLUDED.subtitle, book_text=EXCLUDED.book_text;

在这种情况下,sql 应该更新列,因为 book_special_key 已经存在于 book 表中。

我很熟悉外键约束的更新和删除可能由于完整性原因而失败的原因,但在我的情况下,我没有直接更新 book_id,只是更新 book 表中的列。我还在子表的外键上设置了ON DELETE CASCADE。谁能告诉我为什么会遇到这个问题?

【问题讨论】:

  • 您的更新更改了该行的主键 - 显然更改为新值,但仍从 booksubcategory 表引用旧值。

标签: sql postgresql


【解决方案1】:

插入的行在唯一键 special_book_id 上发生冲突,然后冲突规则尝试更新重复的行。

但是由于冲突而尚未插入并且是 autogen 的 NEW 行的值 book_id 是多少?好吧,要么是 null,要么是新的连续剧。

因此,无论如何,您将 book_id 更新为 null 或新的序列号,但由于旧的 bo​​ok_id 值(即正在消失的)有引用而失败。

删除对 book_id 列的更新,它应该可以工作。

【讨论】:

  • 哦,我明白了。我忘了删除那条线。我找了几个小时,这只是一个简单的错误。感谢您指出这一点。