這是SQLite的版本3.16.0 2016年11月4日SQLite觸發器奇怪的是失敗的唯一約束
這裏是我的測試模式:
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;
我可以看到一個新的行表C
(它獲取每次我摸到B
時間更新):
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
。然後由於某種原因失敗,儘管它在以前的場景中工作得很好。
爲什麼會發生這種情況,我該如何解決?
在我看來,「導致觸發器觸發的語句」是「UPDATE A SET a_id = 2 ...;」,它沒有指定一個「ON CONFLICT」子句,所以在技術上這不適用。 儘管我發現這些doc語句容易解釋,但我認爲,你是對的,因爲'delete' +'insert'確實是一個可行的解決方法。 謝謝! 「 – Knuckles
」默認的衝突解決算法是ABORT。「 –
沒關係。否則,觸發器將同樣失敗 UPDATE B SET descr =「test1」WHERE b_id = 1;',而不是。 – Knuckles