SQlite允许自动增量创建引用另一个表的主键
我通过以下两个表实现了某种继承关系: 让我们填充SQlite允许自动增量创建引用另一个表的主键,sqlite,Sqlite,我通过以下两个表实现了某种继承关系: 让我们填充foo: insert into foo values (1), (3), (4); 现在我可以将3插入bar: insert into bar values(3); -- no error 我无法插入2: insert into bar values(2); -- Error: FOREIGN KEY constraint failed 然而,令我惊讶的是,NULL值可用于生成新键: insert into bar values(NUL
foo
:
insert into foo values (1), (3), (4);
现在我可以将3
插入bar
:
insert into bar values(3); -- no error
我无法插入2
:
insert into bar values(2); -- Error: FOREIGN KEY constraint failed
然而,令我惊讶的是,NULL
值可用于生成新键:
insert into bar values(NULL); -- OK, 4 inserted
insert into bar values(NULL); -- FOREIGN KEY constraint failed
这种行为似乎很奇怪。当我在MySQL中尝试同样的事情时,我会收到一个
ERROR 1048 (23000): Column 'foo_id' cannot be null
这正是我所期望的
当使用子查询在栏中插入新行时,我发现这种行为特别危险:
insert into bar (foo_id) values ((select foo_if from foo where ...))
当foo
中没有匹配项时,它可能会在bar
中悄悄插入随机行,而不是返回错误
这种行为是否符合SQL标准,在什么情况下它会有用,更重要的是,有没有一种方法可以改变这种行为以匹配MySQL的
编辑
下面以一种可能更引人注目(也更可怕)的方式来说明这个问题:
所以我找到了这个问题的答案,这对于不熟悉SQLite的人来说可能有点奇怪
如果未指定值,则声明为integer主键的列将自动填充未使用的整数
在SQLite中,解决这个问题的一种有点神秘的方法是使用声明列int主键
,这会阻止隐式自动处理
然而,我们还没有结束,因为SQLite的另一个独特行为是允许NULL
主键——在上面的示例中,insert-into-bar-values(NULL)
将插入一个带有NULL
主键的新行
要明确禁止主键具有NULL
值,必须将其声明为非NULL:
pragma foreign_keys = ON;
create table foo(foo_id integer primary key);
create table bar(foo_id int primary key not null references foo(foo_id));
insert into foo values (1), (3), (4);
insert into bar values (3);
insert into bar values (2); -- Error: FOREIGN KEY constraint failed
insert into bar values (NULL); -- Error: NOT NULL constraint failed: bar.foo_id
这可能是在SQLite中默认情况下声明指向外部键的主键的方式。我提供的链接中描述了所有令人惊讶或神秘的内容:我的回答中也提到了:因为foo_id被定义为整数主键,这意味着它也是自动递增的,也不使用主键自动递增的键引用另一个也是自动递增的主键。SQLite就是这样工作的。你不知道。你得到的答案提到了所有这些。现在你发布了答案?我的答案给出了我问题的答案。您提供的链接没有(只有“integer主键”特殊行为,甚至没有围绕它的工作)。你的答案更糟糕,没有给出答案,而是说这个问题是错误的,因为类表继承是错误的。你的回答毫无帮助,甚至令人误解。克服它,继续前进。你的回答并不能解决任何问题。这既不是解决方案,也不是解决办法。这是个糟糕的设计。如果你使用这样的设计,你迟早会意识到这一点。也开始阅读文档(我提供的链接)。
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);
-- uh-oh, Jack the Ripper is now part of my family
pragma foreign_keys = ON;
create table foo(foo_id integer primary key);
create table bar(foo_id int primary key not null references foo(foo_id));
insert into foo values (1), (3), (4);
insert into bar values (3);
insert into bar values (2); -- Error: FOREIGN KEY constraint failed
insert into bar values (NULL); -- Error: NOT NULL constraint failed: bar.foo_id