Wir haben eine SQLite CTE UPDATE, die in Versionen bis einschließlich 3.18.0 funktionierte, aber begann in 3.19.0 mit einer FOREIGN KEY-Einschränkung (Fehler 19).SQLite rekursive CTE UPDATE arbeiten in 3.18.0, SQL_CONSTRAINT in 3.19.0
Das folgende Beispiel zeigt eine Spielzeugdatenbank, die das Verhalten zeigt.
sqlite> .version
SQLite 3.18.0 2017-03-28 18:48:43 424a0d380332858ee55bdebc4af3789f74e70a2b3ba1cf29d84b9b4bcf3e2e37
sqlite> .dump t2
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE T2 (Id INTEGER PRIMARY KEY AUTOINCREMENT , ParentId INTEGER NOT NULL , Name TEXT NOT NULL , FavoriteState INT NOT NULL DEFAULT 0, FOREIGN KEY (ParentId) REFERENCES T2(Id));
INSERT INTO T2 VALUES(1,0,'/',2);
CREATE INDEX idx_pid_t2 ON T2 (ParentId);
CREATE INDEX idx_files_favstate_t2 on T2 (FavoriteState);
CREATE UNIQUE INDEX idx_pnc_t2 ON T2 (ParentId, Name);
COMMIT;
sqlite> PRAGMA foreign_keys=ON;
sqlite> WITH RECURSIVE under_favorite_path(parent) AS (VALUES(1) UNION ALL SELECT T2.Id FROM T2 JOIN under_favorite_path ON T2.ParentId = under_favorite_path.parent) UPDATE T2 SET FavoriteState = 1
WHERE Id IN under_favorite_path;
sqlite> select * from t2;
1|0|/|1
sqlite> WITH RECURSIVE under_favorite_path(parent) AS (VALUES(1) UNION ALL SELECT T2.Id FROM T2 JOIN under_favorite_path ON T2.ParentId = under_favorite_path.parent) UPDATE T2 SET FavoriteState = 2
WHERE Id IN under_favorite_path;
sqlite> select * from t2;
1|0|/|2
Das Deaktivieren von Fremdschlüsseln in 3.19.0 ermöglicht das UPDATE.
sqlite> .version
SQLite 3.19.0 2017-05-22 13:58:13 28a94eb282822cad1d1420f2dad6bf65e4b8b9062eda4a0b9ee8270b2c608e40
sqlite> .dump t2
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE T2 (Id INTEGER PRIMARY KEY AUTOINCREMENT , ParentId INTEGER NOT NULL , Name TEXT NOT NULL , FavoriteState INT NOT NULL DEFAULT 0, FOREIGN KEY (ParentId) REFERENCES T2(Id));
INSERT INTO T2 VALUES(1,0,'/',2);
CREATE INDEX idx_pid_t2 ON T2 (ParentId);
CREATE INDEX idx_files_favstate_t2 on T2 (FavoriteState);
CREATE UNIQUE INDEX idx_pnc_t2 ON T2 (ParentId, Name);
COMMIT;
sqlite> PRAGMA foreign_keys=ON;
sqlite> WITH RECURSIVE under_favorite_path(parent) AS (VALUES(1) UNION ALL SELECT T2.Id FROM T2 JOIN under_favorite_path ON T2.ParentId = under_favorite_path.parent) UPDATE T2 SET FavoriteState = 1
WHERE Id IN under_favorite_path;
Error: FOREIGN KEY constraint failed
sqlite> PRAGMA foreign_keys=OFF;
sqlite> WITH RECURSIVE under_favorite_path(parent) AS (VALUES(1) UNION ALL SELECT T2.Id FROM T2 JOIN under_favorite_path ON T2.ParentId = under_favorite_path.parent) UPDATE T2 SET FavoriteState = 1
WHERE Id IN under_favorite_path;
sqlite> select * from t2;
1|0|/|1
Ist das ein Problem mit unserer CTE, die zuvor markiert haben sollen, oder ist dies etwas, das in späteren Versionen SQLite regressiert haben könnte?
Ja, sieht definitiv wie das Verhalten jetzt aus. Ich frage mich, ob diese Änderung beabsichtigt war oder nicht, basierend auf dieser Zeile aus den Versionshinweisen zu 3.19.0 https://www.sqlite.org/releaselog/3_19_0.html, weil ich gelesen habe, dass das Gegenteil von dem ist, was passiert: _Vermeide unnötigen Fremdschlüssel Verarbeitung in UPDATE-Anweisungen, die nicht die Spalten berühren, die durch die Fremdschlüssel eingeschränkt sind._ – ribram
Diese "unnötige Verarbeitung von Fremdschlüsseln" [aktualisiert "nicht betroffene Indizes"] (http://www.sqlite.org/cgi/src/info/477bea9ed0dd0fa6). Es scheint eine andere Veränderung gegeben zu haben ... –