SQLite ON DELETE CASCADE约束无法正常工作

qpgpyjmq  于 2023-06-23  发布在  SQLite
关注(0)|答案(1)|浏览(113)

我试图删除父表中的条目,但子表中的相应条目没有像我预期的那样被删除。这是我创建的两个表:

CREATE TABLE
    IF NOT EXISTS "pages" (
        "id" INTEGER PRIMARY KEY AUTOINCREMENT,
        "title" TEXT,
        "author" TEXT REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
        "creation_date" DATE,
        "publication_date" DATE
    );

CREATE TABLE
    IF NOT EXISTS "blocks"(
        "id" INTEGER PRIMARY KEY AUTOINCREMENT,
        "page_id" INTEGER REFERENCES pages(id) ON DELETE CASCADE ON UPDATE CASCADE,
        "type" TEXT,
        "content" TEXT,
        "position" INTEGER
    );

这是我正在运行的查询:

DELETE FROM pages WHERE id = ?

pages表的条目被正确删除,但删除不会传播。我还添加了PRAGMA foreign_keys = ON;指令,但这并没有解决问题。任何帮助将不胜感激。

1qczuiv0

1qczuiv01#

正如下面的演示所示,您所展示的内容似乎没有任何问题,因此,要么

  • PRAGMA foreign_keys = ON;不工作,或者,
  • 绑定值不是有效的id或
  • 你误解了什么是孩子/父母(即页面的子项是块行)

关于PRAGMA foreign_keys = ON;不工作。考虑以下情况:
为了在SQLite中使用外键约束,必须在编译库时既不定义SQLITE_OMIT_FOREIGN_KEY也不定义SQLITE_OMIT_TRIGGER。如果定义了SQLITE_OMIT_TRIGGER但没有定义SQLITE_OMIT_FOREIGN_KEY,则SQLite的行为与版本3.6.19(2009-10-14)之前的行为相同-外键定义被解析,并且可以使用PRAGMA foreign_key_list进行查询,但不强制执行外键约束。PRAGMA foreign_keys命令在此配置中是无操作的。如果定义了OMIT_FOREIGN_KEY,那么外键定义甚至不能被解析(试图指定外键定义是一个语法错误)。参见https://www.sqlite.org/foreignkeys.html#fk_enable

工作演示

以下是您删除的影响,可用作测试的基础:

/* Just in case cleanup */
DROP TABLE If EXISTS pages;
DROP TABLE IF EXISTS blocks;
DROP TABLE IF EXISTS users;
/* Turn Foreign Keys on (reflecting the status Results 1, 2 and 3) */
PRAGMA foreign_keys;
PRAGMA foreign_keys = off; /* to show the difference between on and off)*/
PRAGMA foreign_keys;
PRAGMA foreign_keys = ON;
PRAGMA foreign_keys;
/* Create the tables */
CREATE TABLE IF NOT EXISTS users (
    id TEXT PRIMARY KEY
    );
CREATE TABLE
    IF NOT EXISTS "pages" (
        "id" INTEGER PRIMARY KEY AUTOINCREMENT,
        "title" TEXT,
        "author" TEXT REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
        "creation_date" DATE,
        "publication_date" DATE
    );
CREATE TABLE
    IF NOT EXISTS "blocks"(
        "id" INTEGER PRIMARY KEY AUTOINCREMENT,
        "page_id" INTEGER REFERENCES pages(id) ON DELETE CASCADE ON UPDATE CASCADE,
        "type" TEXT,
        "content" TEXT,
        "position" INTEGER
    );
/* Populates the tables with some test data */
INSERT INTO users VALUES ('user1'),('user2'),('user3');
INSERT INTO pages VALUES 
    (1,'page1title','user1',datetime('now'),datetime('1984-01-01'))
    ,(2,'page2title','user1',datetime('now','+1 months'),datetime('1992-01-01'))
    ,(3,'page3title','user2',datetime('now','+5 weeks'),datetime('1970-01-01'))
    ,(4,'page4title','user3',datetime('now','+100 days'),datetime('2010-01-01'))
    ,(5,'page5title','user1',datetime('now','+2 years'),datetime('2003-01-01'))
    ,(6,'page6title','user3',datetime('now','+2 months','+3 years','+4 days'),datetime('2015-01-01'))
;
INSERT INTO blocks VALUES
    (1,1,'TYPE1','BLAH1',1)
    ,(2,1,'TYPE2','BLAH2',2)
    ,(3,1,'TYPE2','BLAH3',3)
    ,(4,6,'TYPE3','BLAH4',1)
    ,(5,6,'TYPE4','BLAH5',2)
    ,(6,6,'TYPE1','BLAH6',3)
    ,(7,4,'TYPE3','BLAH7',2)
    ,(8,4,'TYPE2','BLAH8',2)
;
/* Show the core data that has been inserted - Result 4*/
SELECT * FROM pages 
    JOIN users ON pages.author = users.id
    JOIN blocks ON blocks.page_id = pages.id
;
/* Delete a single page */
DELETE FROM pages WHERE id = 4;
/* Show the data after the deletion - Result 5*/
SELECT * FROM pages 
    JOIN users ON pages.author = users.id
    JOIN blocks ON blocks.page_id = pages.id
;
/* Show the blocks, as blocks with id 7 and 8 should have been deleted through propogation - Result 6*/
SELECT * FROM blocks;
/* Cleanup the test environment */
DROP TABLE If EXISTS pages;
DROP TABLE IF EXISTS blocks;
DROP TABLE IF EXISTS users;

结果

  • 结果1 foreign_keys 1
  • 结果2 foreign_keys 0
  • 结果3 foreign_keys 1
  • 结果4(初始数据):-

  • 结果5(删除id为4的页面后):-

  • 结果6(来自块表的所有剩余行):

*即删除id为4的页面行导致相关块行通过传播被删除

相关问题