Иногда мне хотелось бы более внимательно прочитать документы .
Каждое ограничение внешнего ключа в SQLite классифицируется как немедленное или отложенное. Ограничения по внешнему ключу являются немедленными по умолчанию. (...)
Если оператор изменяет содержимое базы данных так, что немедленное ограничение внешнего ключа нарушаетсяв заключении утверждения выдается исключение , и последствия утверждения возвращаются.Напротив, если оператор изменяет содержимое базы данных таким образом, что нарушается ограничение отложенного внешнего ключа , нарушение не сообщается немедленно.Отложенные ограничения внешнего ключа не проверяются, пока транзакция не попытается выполнить COMMIT.
Таким образом, таблица может объявить внешний ключ как DEFERRABLE 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_foreign_keys
:
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;
Должен сказать, я не понимаю, как использовать непосредственные внешние ключи, и я не понимаю, почему они должны использоваться по умолчанию - разве что по соображениям производительности?