Pegue o seguinte código:
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
Como isso é legítimo no sqlite? Nem mesmo um aviso é gerado. Isso é por boas razões, por razões de legado, há algo na documentação sobre isso que eu não encontrei? Para mim, isso é preocupante e acredito que nenhum outro SQL DB se comporte dessa forma.
INTEGER PRIMARY KEY
colunas no SQLite são um tanto estranhas. Elas são tomadas por padrão para significar umROWID
ouAUTOINCREMENT
, ou em outras linguagens que seriaSERIAL
ouIDENTITY
.Dos documentos :
O documento vinculado afirma:
Agora, combinado com seu uso um tanto estranho de subconsultas, fica claro o que está acontecendo.
A subconsulta, quando executada sozinha, não retorna nenhuma linha:
Quando colocado dentro de uma subconsulta escalar, "no rows" é convertido para um
NULL
. Então se torna:O mecanismo então decide criar um valor do nada, que por acaso corresponde a um valor existente na chave estrangeira.
Também notei sua falta de especificação de quais colunas você está inserindo, o que pode ser um problema para você mais tarde.
A solução correta é especificar
WITHOUT ROWID
na sua tabela. Isso significa que o mecanismo não gerará um valor para essa coluna e, portanto, a inserção falhará. Você também precisa especificar explicitamente aNOT NULL
restrição, porque o SQLite não adiciona isso por padrão na maioria dos casos.Você também deveria ter alterado seu
INSERT
para um mais normalINSERT...SELECT...
, sem uma subconsulta. Isso teria resultado na inserção de nenhuma linha em primeiro lugar.