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 算法。