INSERT OR REPLACE +外键ON DELETE CASCADE工作得太好了

时间:2012-03-26 14:28:20

标签: sqlite

我目前正在尝试创建一个sqlite数据库,我可以从另一个sqlite数据库导入一个表(无法附加),并为每一列添加一些额外的数据。

由于没有INSERT OR UPDATE我想出了这个:
我正在考虑将数据拆分为两个表并在之后加入它们,因此我可以将整个导入转储到一个表中,替换所有更改的内容并分别管理额外数据,因为导入时不会更改。

第一个表格(我们称之为base_data)看起来像

local_id | remote_id | base_data1 | base_data2 | ...
---------+-----------+------------+------------+----

除了local_id之外,一切都只是远程数据库的镜像(我可能会添加一个同步时间戳,但现在无关紧要。)

第二个表看起来很相似,但remote_id设置为外键

remote_id | extra_data1 | extra_data2 | ...
----------+-------------+-------------+----

   CREATE TABLE extra_data (
       remote_id INTEGER 
           REFERENCES base_data(remote_id)
           ON DELETE CASCADE ON UPDATE CASCADE
           DEFERRABLE INITIALLY DEFERRED,
       extra_data1 TEXT,
       extra_data2 TEXT,
       /* etc */
   )

现在我的想法是简单地INSERT OR REPLACE INTO base_data ...值,因为我导入的数据库没有同步时间戳或者我必须比较所有内容以找出我需要的行UPDATE /什么到INSERT

但问题在于:INSERT OR REPLACE实际上是DELETE后跟INSERT,删除部分会触发外键ON DELETE我认为我可以阻止它制定约束DEFERRED。如果我在事务中包装INSERT OR REPLACE,它也不起作用。虽然声明后存在相同的外键,但它总是删除我的额外数据。

ON DELETE完成之前,是否可以阻止INSERT OR REPLACE触发?也许一些特殊的交易模式/ pragma?

2 个答案:

答案 0 :(得分:3)

如果我用以下触发器替换ON DELETE CASCADE部分似乎有用:

CREATE TRIGGER on_delete_trigger
   AFTER DELETE ON base_data
   BEGIN
       DELETE FROM extra_data WHERE extra_data.remote_id=OLD.remote_id;
   END;

该触发器仅由DELETE语句触发,到目前为止应解决我的问题。

(问题中OP提供的答案)

ClientWebSocket class的其他信息,引用jmathew

  

REPLACE冲突解决策略删除行以满足约束时,当且仅当启用了递归触发时,删除触发器才会触发。

答案 1 :(得分:0)

这种行为的原因是什么,PostgreSQL团队有explanation

是的,据我们所知,这是根据SQL规范。约束检查可以 推迟到交易结束,但“引用动作”不是 延期的它们总是在触发语句期间发生。对于 实例SQL99将级联删除的结果描述为 引用行立即被“标记为删除”,然后

  1. 所有标记为删除的行均被有效删除 在SQL语句的末尾,在检查任何 完整性约束。