SQLite外键ON跨层级表删除CASCADE(RESTRICT)

时间:2014-03-22 13:09:35

标签: sql database sqlite

我在SQLite数据库中有表,它由外键引用,如树结构:

table1:
 id
 <other_fields>

table2:
 id
 table1_id (ON DELETE CASCADE)
 <other_fileds>

table3:
 id
 table2_id (ON DELETE CASCADE)
 <other_fields>

etc...

此数据来自服务器。 但是用户可以将自己的数据存储在数据库中(例如&#34;注释&#34;到任何记录)。 用户数据存储在附加表中,分别引用到Table1,Table2等

table1_user_data:
 id
 table1_id (ON DELETE RESTRICT) - to forbid deleting if user data exists

table2_user_data:
 id
 table2_id (ON DELETE RESTRICT)

如果我从根表(table1)中删除数据,我想保留属于&#34; branches&#34;的记录。对于用户数据,必须删除其他数据。 但是当我执行DELETE FROM table1时 - 发生了外键约束并且没有(!)数据被删除。 但我想删除用户数据记录未引用的所有数据。

(例如,如果我只有一条评论(用户数据),引用table2中的一条记录,那么在删除之后我希望有这条评论,table2中的相应记录和table1中的一条记录(在哪条记录上)在表2中引用))

实施此策略的最佳方式是什么?

1 个答案:

答案 0 :(得分:0)

当您告诉数据库删除某些记录时,某些记录实际上没有被删除(由于违反约束,或者从触发器引发错误或任何其他原因),那么整个DELETE语句被认为是失败了,并且流产了。

删除记录子集的唯一方法是向DELETE语句本身添加适当的过滤器:

DELETE FROM table1
WHERE id NOT IN (SELECT table1_id
                 FROM table1_user_data)
  AND id NOT IN (SELECT table1_id
                 FROM table2
                 WHERE id IN (SELECT table2_id
                              FROM table2_user_data))
  ... etc.

或者,分别删除每条记录,以便您可以忽略约束违规错误,并且可以继续使用下一条记录:

SELECT id FROM table1;
-- for each returned id:
DELETE FROM table1 WHERE id = 123;  -- ignore constraint errors
DELETE FROM table1 WHERE id = 456;  -- ignore constraint errors
DELETE FROM table1 WHERE id = 789;  -- ignore constraint errors
...