SQLite ON CONFLICT 子句的正确用法
Correct usage of the SQLite ON CONFLICT clause
我有一个 SQLite 数据库,其中包括以下 table.
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
用于确保所有三列 data
、link
和 bias_type
的两行不能具有相同的值。所以假设我这样做
INSERT INTO biases (data,link,bias_type,ignores) VALUES(1,1,1,1);
事情按预期进行 - table 中插入了新行。如果我再次发出相同的 INSERT,我会得到错误
UNIQUE CONSTRAINT FAILED: 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 增加了行中 ignores
列的值与匹配的 data
, link
和 bias_type
值。
然而,这只是实验的结果。从 SQLite 文档中我并不能立即清楚这确实是 ON CONFLICT
应该表现的方式——即可以给它两个或多个冲突约束来检查。我所说的两个或多个约束的意思是在 CONFLICT(...)
内指定多个逗号分隔的列,就像我在上面的示例中所做的那样。
我怀疑这是正确的用法,因为我只是指定了一个 CONFLICT
条件来复制我指定的 CONSTRAINT
。但是,我在文档的任何地方都看不到这一点的明确解释。如果有人能证实这一点,我将不胜感激。
来自UPSERT:
UPSERT is a special syntax addition to INSERT that causes the INSERT
to behave as an UPDATE or a no-op if the INSERT would violate a
uniqueness constraint.
和:
The special UPSERT processing happens only for uniqueness constraint
on the table that is receiving the INSERT.
因此 DO UPDATE
部分不是由任何约束冲突触发,而是由唯一约束违规触发。
还有:
The syntax that occurs in between the "ON CONFLICT" and "DO" keywords
is called the "conflict target". The conflict target specifies a
specific uniqueness constraint that will trigger the upsert.
因此不可能在一个语句中检查两个或更多个冲突约束。
但是,您可以使用单独的 UPSERT
语句来检查 2 个不同的唯一约束违规。
请参阅简化的 demo,其中我向 table:
添加了 1 个 UNIQUE
约束
CONSTRAINT con_scraps UNIQUE(scraps)
我有一个 SQLite 数据库,其中包括以下 table.
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
用于确保所有三列 data
、link
和 bias_type
的两行不能具有相同的值。所以假设我这样做
INSERT INTO biases (data,link,bias_type,ignores) VALUES(1,1,1,1);
事情按预期进行 - table 中插入了新行。如果我再次发出相同的 INSERT,我会得到错误
UNIQUE CONSTRAINT FAILED: 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 增加了行中 ignores
列的值与匹配的 data
, link
和 bias_type
值。
然而,这只是实验的结果。从 SQLite 文档中我并不能立即清楚这确实是 ON CONFLICT
应该表现的方式——即可以给它两个或多个冲突约束来检查。我所说的两个或多个约束的意思是在 CONFLICT(...)
内指定多个逗号分隔的列,就像我在上面的示例中所做的那样。
我怀疑这是正确的用法,因为我只是指定了一个 CONFLICT
条件来复制我指定的 CONSTRAINT
。但是,我在文档的任何地方都看不到这一点的明确解释。如果有人能证实这一点,我将不胜感激。
来自UPSERT:
UPSERT is a special syntax addition to INSERT that causes the INSERT to behave as an UPDATE or a no-op if the INSERT would violate a uniqueness constraint.
和:
The special UPSERT processing happens only for uniqueness constraint on the table that is receiving the INSERT.
因此 DO UPDATE
部分不是由任何约束冲突触发,而是由唯一约束违规触发。
还有:
The syntax that occurs in between the "ON CONFLICT" and "DO" keywords is called the "conflict target". The conflict target specifies a specific uniqueness constraint that will trigger the upsert.
因此不可能在一个语句中检查两个或更多个冲突约束。
但是,您可以使用单独的 UPSERT
语句来检查 2 个不同的唯一约束违规。
请参阅简化的 demo,其中我向 table:
UNIQUE
约束
CONSTRAINT con_scraps UNIQUE(scraps)