【问题标题】:Correct usage of the SQLite ON CONFLICT clause正确使用 SQLite ON CONFLICT 子句
【发布时间】:2020-06-02 20:09:52
【问题描述】:

我有一个 SQLite 数据库,其中包括下表。

CREATE TABLE IF NOT EXISTS biases
(
 data INTEGER NOT NULL,
 link INTEGER DEFAULT 0,
 bias_type INTEGER,
 ignores INTEGER DEFAULT 0,
 desists INTEGER DEFAULT 0,
 encashes INTEGER DEFAULT 0, 
 accesses INTEGER DEFAULT 0,
 scraps INTEGER DEFAULT 0,
 CONSTRAINT pk_bias_mix PRIMARY KEY(data,link,bias_type)
);  

约束pk_bias_mix 用于确保没有两行可以对datalinkbias_type 列的所有三列具有相同的值。所以假设我这样做了

INSERT INTO biases (data,link,bias_type,ignores) VALUES(1,1,1,1);

一切正常 - 在表中插入了一个新行。如果我再次发出相同的 INSERT,我会收到错误

唯一约束失败:biases.data,biases.link,biases.bias_type

正如预期的那样。因此,我尝试使用 SQLite ON CONFLICT 子句

INSERT INTO biases (data,link,bias_type,ignores) VALUES(1,1,1,1)
ON CONFLICT(data,link,bias_type) DO UPDATE SET ignores = ignores + 1;

它按我希望的那样工作 - SQLite 没有添加新行或抛出错误,而是使用匹配的 datalinkbias_type 值增加了行中 ignores 列的值.

不过,这只是实验的结果。从 SQLite 文档中我并不清楚这确实是 ON CONFLICT 应该如何表现 - 即可以给它两个或多个冲突约束进行检查。我所说的两个或更多约束的意思是在CONFLICT(...) 中指定多个逗号分隔的列,就像我在上面的示例中所做的那样。

我怀疑这是正确的用法,因为我只是指定了一个CONFLICT 条件来复制我指定的CONSTRAINT。但是,我在文档中的任何地方都看不到这一点。对于任何能够证实这一点的人,我将不胜感激。

【问题讨论】:

    标签: sqlite upsert


    【解决方案1】:

    来自UPSERT

    UPSERT 是对 INSERT 的一种特殊语法,它会导致 INSERT 如果 INSERT 违反了 唯一性约束。

    和:

    特殊的 UPSERT 处理仅针对唯一性约束发生 在接收 INSERT 的表上。

    所以DO UPDATE 部分不是由任何约束冲突触发的,而是由唯一的约束冲突触发的。

    还有:

    出现在“ON CONFLICT”和“DO”关键字之间的语法 被称为“冲突目标”。冲突目标指定了一个 将触发 upsert 的特定唯一性约束

    因此不可能在一个语句中检查两个或更多冲突约束。
    但是,您可以使用单独的 UPSERT 语句来检查 2 个不同的唯一约束违规。

    查看简化的demo,我在其中向您的表添加了另外1 个UNIQUE 约束:

    CONSTRAINT con_scraps UNIQUE(scraps)
    

    【讨论】:

    • 我的问题措辞有些含糊,导致您错误地解释了我提到的两个或多个冲突。我现在改写了这个问题。
    • 答案中已经提到了这一点:冲突目标指定了将触发 upsert 的特定唯一性约束,因为指定了多个逗号分隔的列 参考1 个唯一约束
    • 如果逗号分隔的列列表没有引用定义的特定唯一约束,则代码将不会运行并出现错误。
    猜你喜欢
    • 2021-03-05
    • 2017-11-18
    • 2016-05-11
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2021-11-07
    相关资源
    最近更新 更多