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

Posted

技术标签:

【中文标题】是否可以在使用 sqlite 插入时忽略外键冲突?【英文标题】:Is it possible to ignore foreign key conflicts on insert with sqlite? 【发布时间】:2020-12-29 19:22:48 【问题描述】:

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

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 是否提供了这样做的方法?

【问题讨论】:

如果要违反外键约束有什么意义?如果要添加 master_node 中不存在的记录,则不要删除约束。 insert or ignore 仅忽略 UNIQUE 约束违规。 @Ivar 我希望 FK 约束阻止我添加违反约束的行。我只想要来自master_node 的具有book_name 的行,但是如果我正在执行批量插入并且我有违反约束的行,我只想忽略这些行,而不是回滚整个插入。 @forpas 是的,我注意到它只适用于 uniquecheck,我只是在寻找相同的功能,但要使用外键约束。 这能回答你的问题吗? insert or ignore rows that violate foreign key constraints sqlite 【参考方案1】:

没有等效的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 

【讨论】:

谢谢。我希望能够使用 FK,因为无论如何我都需要它们进行级联删除,但是这个解决方案看起来是解决我的问题的最干净的方法。

以上是关于是否可以在使用 sqlite 插入时忽略外键冲突?的主要内容,如果未能解决你的问题,请参考以下文章

在 SQLite 中将 SQL 数据插入到链接(外键)表中

插入语句与外键冲突

Android 批量插入或忽略 JSONArray

使用 pl/sql 函数插入多个表会导致外键冲突

世博sqlite外键

Android中使用SQLite的外键约束?在删除级联