Sql &引用;外键约束失败“;在事务期间更新依赖表时

Sql &引用;外键约束失败“;在事务期间更新依赖表时,sql,sqlite,Sql,Sqlite,我有三个表,它们的链依赖关系如下: pragma foreign_keys = ON; create table foo (id integer primary key); create table bar (id integer primary key references foo(id)); create table baz (id integer primary key references bar(id)); insert into foo values (1), (2); insert

我有三个表,它们的链依赖关系如下:

pragma foreign_keys = ON;
create table foo (id integer primary key);
create table bar (id integer primary key references foo(id));
create table baz (id integer primary key references bar(id));
insert into foo values (1), (2);
insert into bar values (1);
insert into baz values (1);
create table foo (id integer primary key);
create table bar (id integer primary key references foo(id) on update cascade);
create table baz (id integer primary key references bar(id) on update cascade);
我想更新子表
bar
baz
。但是,当在一个事务中更新它们时,我得到一个错误:

begin;
update bar set id = 2 where id = 1;
update baz set id = 2 where id = 1;
commit;
-- Error: FOREIGN KEY constraint failed

如何同时更新子表以避免外键约束错误?

您可能正试图避免此错误。。。但是

begin;
delete baz where id = 1;
delete bar where id = 1;
insert into bar values (2);
insert into baz values (2);
commit;

如果在每个外键上设置了更新级联上的
,则关系主键端的更改应传播到外键端的字段。可以这样设置:

pragma foreign_keys = ON;
create table foo (id integer primary key);
create table bar (id integer primary key references foo(id));
create table baz (id integer primary key references bar(id));
insert into foo values (1), (2);
insert into bar values (1);
insert into baz values (1);
create table foo (id integer primary key);
create table bar (id integer primary key references foo(id) on update cascade);
create table baz (id integer primary key references bar(id) on update cascade);
然后,您只需要像这样更新bar.id,更改将在baz.id中自动发生

begin;
update bar set id = 2 where id = 1;
commit;

有时候我希望我能读得更仔细些

SQLite中的每个外键约束分为立即约束和延迟约束默认情况下,外键约束是即时的。(…)

如果一条语句修改数据库的内容,从而在结束语句时违反了立即外键约束,则会抛出一个异常,并恢复该语句的效果。相反,如果语句修改数据库的内容,从而违反了延迟外键约束,则不会立即报告违反情况。在事务尝试提交之前,不会检查延迟外键约束。

因此,表可以将外键声明为
可延迟的INITIALLY DEFERRED
,以允许这种更新

pragma foreign_keys = ON;
create table foo (id integer primary key);
create table bar (id integer primary key references foo(id) deferrable initially deferred);
create table baz (id integer primary key references bar(id) deferrable initially deferred);
insert into foo values (1), (2);
insert into bar values (1);
insert into baz values (1);

begin;
update bar set id = 2 where id = 1;
update baz set id = 2 where id = 1;
commit;
但由于sqlite不允许轻易地修改表,所以很高兴知道,在具有立即外键的现有表上,可以使用
defer\u-foreign\u-keys
pragma:

pragma foreign_keys = ON;
create table foo (id integer primary key);
create table bar (id integer primary key references foo(id));
create table baz (id integer primary key references bar(id));
insert into foo values (1), (2);
insert into bar values (1);
insert into baz values (1);

pragma defer_foreign_keys=ON;
begin;
update bar set id = 2 where id = 1;
update baz set id = 2 where id = 1;
commit;
我必须说,我不理解立即外键的用法,我也不明白为什么它们应该是默认值——也许是出于性能原因