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

zap*_*apl 14 sqlite

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

因为没有INSERT OR UPDATE我提出这个:
我正在考虑将数据分成两个表并在之后加入它们所以我可以将整个导入转储到一个表中,替换所有更改并分别管理额外数据,因为这不会改变在进口.

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

local_id | remote_id | base_data1 | base_data2 | ...
---------+-----------+------------+------------+----
Run Code Online (Sandbox Code Playgroud)

除了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 */
   )
Run Code Online (Sandbox Code Playgroud)

现在我的想法只是简单的INSERT OR REPLACE INTO base_data ...值,因为我导入的数据库没有同步时间戳或任何东西,我将不得不比较一切,以找出我有什么行UPDATE/什么INSERT.

但这里存在的问题INSERT OR REPLACE是:实际上是一个DELETE后跟a INSERT和删除部分触发外键ON DELETE,我认为我可以通过制定约束来阻止它DEFERRED.如果我INSERT OR REPLACE在事务中包装它也不起作用.尽管在语句后存在相同的外键,但它总是删除我的额外数据.

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

Bar*_*zKP 4

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;
Run Code Online (Sandbox Code Playgroud)

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

(OP在问题中提供的答案)

jmathew引用文档的附加信息:

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