ON CONFLICT 子句是 SQLite 特有的非標準擴充功能,可出現在許多其他 SQL 指令中。本文件給予其一個專屬區段,因為它並非標準 SQL 的一部分,因此可能不熟悉。
此處所述的 ON CONFLICT 子句自 3.0.0 版 (2004-06-18) 之前就已成為 SQLite 的一部分。「ON CONFLICT」一詞也是 UPSERT 的一部分,後者是 3.24.0 版 (2018-06-04) 中新增的 INSERT 擴充功能。請勿混淆「ON CONFLICT」一詞這兩種不同的用法。
ON CONFLICT 子句的語法如上所示,適用於 CREATE TABLE 指令。對於 INSERT 和 UPDATE 指令,關鍵字「ON CONFLICT」會被「OR」取代,以便語法讀起來更自然。例如,我們使用「INSERT OR IGNORE」取代「INSERT ON CONFLICT IGNORE」。關鍵字會變更,但子句的含義不變。
ON CONFLICT 子句適用於 UNIQUE、NOT NULL、CHECK 和 PRIMARY KEY 約束。ON CONFLICT 演算法不適用於 FOREIGN KEY 約束。有五種衝突解決演算法可供選擇:ROLLBACK、ABORT、FAIL、IGNORE 和 REPLACE。預設的衝突解決演算法為 ABORT。以下是它們的含義
當適用的約束條件違規發生時,ROLLBACK 解析演算法會中斷目前的 SQL 陳述,並顯示 SQLITE_CONSTRAINT 錯誤,並回滾目前的交易。如果沒有交易正在進行中(除了在每個指令中建立的隱含交易之外),ROLLBACK 解析演算法會與 ABORT 演算法以相同的方式運作。
當適用的約束條件違規發生時,ABORT 解析演算法會中斷目前的 SQL 陳述,並顯示 SQLITE_CONSTRAINT 錯誤,並撤銷目前的 SQL 陳述所做的任何變更;但同一交易中先前 SQL 陳述所造成的變更會保留,而且交易仍然進行中。這是預設行為,也是 SQL 標準指定的行為。
當適用的約束條件違規發生時,FAIL 解析演算法會中斷目前的 SQL 陳述,並顯示 SQLITE_CONSTRAINT 錯誤。但是,FAIL 解析並不會撤銷失敗的 SQL 陳述的先前變更,也不會結束交易。例如,如果 UPDATE 陳述在嘗試更新的第 100 列中遇到約束條件違規,則前 99 列的變更會保留,但第 100 列及以後的變更則永遠不會發生。
FAIL 行為僅適用於唯一性、NOT NULL 和 CHECK 約束條件。而 外來鍵約束條件 違規則會造成 ABORT。
當適用的約束違規發生時,IGNORE 解析演算法會略過包含約束違規的一列,並繼續處理 SQL 陳述式的後續列,就像什麼事都沒發生一樣。在包含約束違規的一列之前和之後的其他列會正常插入或更新。當使用 IGNORE 衝突解析演算法時,不會傳回唯一性、NOT NULL 和 UNIQUE 約束錯誤。但是,IGNORE 衝突解析演算法會像 ABORT 一樣處理 外來鍵約束 錯誤。
當 UNIQUE 或 PRIMARY KEY 約束違規發生時,REPLACE 演算法會刪除在插入或更新目前列之前導致約束違規的先前存在列,然後命令會繼續正常執行。如果發生 NOT NULL 約束違規,REPLACE 衝突解析會將 NULL 值替換為該欄位的預設值,或者如果該欄位沒有預設值,則會使用 ABORT 演算法。如果發生 CHECK 約束 或 外來鍵約束 違規,REPLACE 衝突解析演算法會像 ABORT 一樣處理。
當 REPLACE 衝突解析策略刪除列以滿足約束時,刪除觸發器 僅在啟用 遞迴觸發器 時才會觸發。
對於由 REPLACE 衝突解析策略刪除的列,不會呼叫 更新掛鉤。REPLACE 也不會遞增 變更計數器。本段落中定義的例外行為可能會在未來版本中變更。
在 INSERT 或 UPDATE 的 OR 子句中指定的演算法會覆寫在 CREATE TABLE 中指定的任何演算法。如果未在任何地方指定演算法,則會使用 ABORT 演算法。