首页 > 解决方案 > 更新或删除违反外键约束

问题描述

我有两个如下所示的表。

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_keybook 表中已经存在。

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

标签: sqlpostgresql

解决方案


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

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

因此,无论如何,您将 book_id 更新为 null 或新的序列号,但它会失败,因为正在消失的旧 book_id 值具有引用。

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


推荐阅读