Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQlite允许自动增量创建引用另一个表的主键_Sqlite - Fatal编程技术网

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