ON CONFLICT 子句是 SQLite 特有的非标准扩展,可以出现在许多其他 SQL 命令中。它在本文档中拥有独立的章节,因为它不是标准 SQL 的一部分,因此可能不为人所熟知。
此处描述的 ON CONFLICT 子句从 SQLite 3.0.0 版本(2004-06-18)之前就已经存在。短语“ON CONFLICT”也是 UPSERT 的一部分,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 算法。