这是SQLite版本3.16.0 2016-11-04
这是我的测试架构:
PRAGMA foreign_keys = ON;
CREATE TABLE A (a_id integer primary key, x int);
CREATE TABLE B (b_id integer primary key, a_id integer not null references A(a_id) ON DELETE RESTRICT ON UPDATE CASCADE, descr text);
CREATE TABLE C (id integer primary key, dt DATETIME DEFAULT CURRENT_TIMESTAMP);
CREATE TRIGGER Tb after update on B begin
replace into C (id) select NEW.b_id;
end;
这里有一些测试数据(根据.dump
):
INSERT INTO "A" VALUES(1, 5000);
INSERT INTO "B" VALUES(1, 1, 'none');
现在,如果我手动更新表B
中的行,就像这样:
UPDATE B SET descr = "test1" WHERE b_id = 1;
我可以在表B
中看到一个新行(每当我触摸C
时都会更新):
1|2017-04-17 21:59:42
我也可以手动"触摸" C
与触发器完成的方式相同:
replace into C (id) select 1;
正如预期的那样,dt
列会更新。到目前为止都很好。
但突然间,如果我更改a_id
,则引用B
:
UPDATE A SET a_id = 2 WHERE a_id = 1;
我得到Error: UNIQUE constraint failed: C.id
根据我的理解,从B.a_id
到A.a_id
的外键会更新B
的行。这导致触发器试图触及C
。然后出于某种原因失败了,尽管它在之前的场景中运行得非常好。
为什么会发生这种情况,我该如何解决?
答案 0 :(得分:1)
您使用的是REPLACE command,
是" INSERT OR REPLACE"的别名。 INSERT命令的变体。
ON CONFLICT子句可以指定为触发器正文中UPDATE或INSERT操作的一部分。但是,如果将ON CONFLICT子句指定为导致触发器触发的语句的一部分,则使用外部语句的冲突处理策略。
因此,当外部命令是UPDATE时,您的REPLACE也会变为UPDATE。
作为解决方法,请使用适当的DELETE和INSERT命令替换REPLACE。