以下面的代码为例:
pragma foreign_keys = ON;
create table people(people_id integer primary key, name text not null);
insert into people (name) values ("Mom"), ("Jack the Ripper");
create table family_member(people_id integer primary key references people(people_id));
insert into family_member values ((select people_id from people where name = "Mom"));
insert into family_member values ((select people_id from people where name = "Dad")); -- silent error here
select name from family_member inner join people using (people_id);
-- Jack the Ripper is part of the family
这在 sqlite 中怎么会是合法的?甚至没有发出警告。这是出于好的理由,还是出于遗留原因,文档中是否有我尚未找到的内容?对我来说,这令人担忧,我相信没有其他 SQL DB 会这样做。
INTEGER PRIMARY KEY
SQLite 中的列相当奇怪。它们默认表示为ROWID
或AUTOINCREMENT
,或者在其他语言中表示为SERIAL
或IDENTITY
。来自文档:
该链接文件指出:
现在,结合您对子查询的相当奇怪的使用,很清楚发生了什么。
子查询单独执行时,不会返回任何行:
当放置在标量子查询中时,“无行”将转换为
NULL
。因此它变成:然后引擎决定突然创建一个值,而该值恰好与外键中的现有值相匹配。
我还注意到您没有指定要插入哪些列,这可能会在以后给您带来麻烦。
正确的解决方案是在您的表上指定
WITHOUT ROWID
。这意味着引擎不会为该列生成值,因此插入将失败。您还需要明确指定约束NOT NULL
,因为 SQLite 在大多数情况下不会默认添加它。您还应该将您的查询更改
INSERT
为更正常的INSERT...SELECT...
没有子查询的查询,这将导致首先不插入任何行。