是否可以忽略使用 sqlite 插入时的外键冲突?

Is it possible to ignore foreign key conflicts on insert with sqlite?

这是我拥有的两个表的匿名表示:

create table if not exists master_node (
    book_name text primary key on conflict ignore not null
);

create table if not exists category_table (
    book_name text not null,
    category text not null,
    foreign key(book_name) references master_node(book_name) on delete cascade,
    unique(book_name, category) on conflict ignore
);

当我将代码插入表中时:

insert into master_node
    (book_name)
values
    ('Harry Potter'),
    ('Foundation'),
    ('The Catcher in the Rye')

insert or ignore into category_table
    (book_name, category)
values
    (Harry Potter', 'Fiction'),
    ('Harry Potter', 'Fantasy'),
    ('Foundation', 'Fiction'),
    ('Foundation', 'Science Fiction'),
    ('The Catcher in the Rye', 'Coming-of-age'),
    ('Moby Dick', 'Adventure')

我收到 [SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed) 错误,事务被回滚。

我希望通过使用 insert or ignore 我能够简单地跳过违反外键约束的行。我一直无法找到一种方法来获得这种行为。 sqlite 是否提供这样做的方法?

没有 INSERT OR IGNORE 的等效项,它仅适用于违反 UNIQUE 约束和违反 FOREIGN KEY 约束的情况。

作为解决方法,您可以在 INSERT ... SELECT 语句中使用 EXISTS

WITH cte(book_name, category) AS (
    VALUES 
    ('Harry Potter', 'Fiction'),
    ('Harry Potter', 'Fantasy'),
    ('Foundation', 'Fiction'),
    ('Foundation', 'Science Fiction'),
    ('The Catcher in the Rye', 'Coming-of-age'),
    ('Moby Dick', 'Adventure')
)
INSERT INTO category_table (book_name, category)
SELECT c.book_name, c.category
FROM cte c
WHERE EXISTS (SELECT 1 FROM master_node m WHERE m.book_name = c.book_name)

参见demo
结果:

> book_name              | category       
> :--------------------- | :--------------
> Harry Potter           | Fiction        
> Harry Potter           | Fantasy        
> Foundation             | Fiction        
> Foundation             | Science Fiction
> The Catcher in the Rye | Coming-of-age