多个 UNIQUE 字段的 ON DUPLICATE KEY UPDATE 的 MySQL 行为
Posted
技术标签:
【中文标题】多个 UNIQUE 字段的 ON DUPLICATE KEY UPDATE 的 MySQL 行为【英文标题】:MySQL behavior of ON DUPLICATE KEY UPDATE for multiple UNIQUE fields 【发布时间】:2013-04-28 23:31:01 【问题描述】:从 mysql 4.1.0 开始,可以添加 ON DUPLICATE KEY UPDATE
语句来指定插入的值(使用 INSERT
或 SET
或 VALUES
)已经在目标表 w.r.t 中时的行为。 PRIMARY KEY
或一些 UNIQUE
字段。如果PRIMARY KEY
或某些UNIQUE
字段的值已在表中,则INSERT
将替换为UPDATE
。
ON DUPLICATE KEY UPDATE
在有多个的情况下如何表现
UNIQUE
我的表中的字段?
如果UNIQUE
字段匹配,我可以只更新一次吗?
只有当UNIQUE
两个字段同时匹配时,我才能更新吗?
【问题讨论】:
【参考方案1】:考虑
INSERT INTO table (a,b,c) VALUES (1,2,3)
-> ON DUPLICATE KEY UPDATE c=c+1;
如果 a 和 b 是 UNIQUE
字段,则 UPDATE
出现在 a = 1 OR b = 2
上。此外,当两个或更多条目满足条件a = 1 OR b = 2
时,仅更新一次。
Ex here table table with Id and Name UNIQUE
字段
Id Name Value
1 P 2
2 C 3
3 D 29
4 A 6
如果查询是
INSERT INTO table (Id, Name, Value)
VALUES (1, C, 7);
然后我们得到
Id Name Value
1 P 2
2 C 3
3 D 29
4 A 6
1 C 7
这违反了 Id 和 Name 的唯一性。现在有了
INSERT INTO table (Id, Name, Value)
VALUES (1, C, 7)
ON DUPLICATE KEY UPDATE Value = 7;
我们得到
Id Name Value
1 P 7
2 C 7
3 D 29
4 A 6
多个键的行为如下
如果UNIQUE
字段之一等于要插入的值,则执行ON DUPLICATE KEY UPDATE
中的UPDATE
。这里,UPDATE
在Id = 1 OR Name = C
上执行。相当于
UPDATE table
SET Value = 7
WHERE Id = 1 OR Name = C;
如果我只想要一个更新,对于任一键怎么办
可以使用UPDATE
语句和LIMIT
关键字
UPDATE table
SET Value = 7
WHERE Id = 1 OR Name = C
LIMIT 1;
这将给
Id Name Value
1 P 7
2 C 3
3 D 29
4 A 6
如果我只想在两个键的值都匹配的情况下进行一次更新怎么办
一种解决方案是ALTER TABLE
并使PRIMARY KEY
(或唯一性)在这两个字段上都起作用。
ALTER TABLE table
DROP PRIMARY KEY,
ADD PRIMARY KEY (Id, Name);
现在开始
INSERT INTO table (Id, Name, Value)
VALUES (1, C, 7)
ON DUPLICATE KEY UPDATE Value = 7;
我们得到
Id Name Value
1 P 2
2 C 3
3 D 29
4 A 6
1 C 7
因为没有找到重复项(在两个键上)。
【讨论】:
如果您有一个包含两列作为主键的表,并且希望使用 ON DUPLICATE KEY,必须避免向 pk 列添加唯一索引,因为如果 pk1 或 pk2 存在于值。 有没有办法在第 2 列上设置唯一约束,但有它不会影响此重复键更新操作吗?这意味着如果不满足唯一约束,则插入或更新将失败。 我的测试与这个答案声称的相矛盾(在 MySQL 8.0.22 上)。 只有一个重复的行被更新,它似乎是发现重复的第一个索引的行。烦人,因为很难控制索引顺序,而且索引顺序应该无关紧要。 (请注意,PK 始终是第一个唯一索引,因此 PK 副本将始终是更新的第一个竞争者 - 这是所有这一切中唯一合乎逻辑的事情。)【参考方案2】:MySQL 的行为... 它的行为符合预期,即执行 ON DUPLICATE KEY 子句。
我可以有一个更新... 实际上,您只有一个 ON DUPLICATE KEY 子句,因此您需要放置一些代码来区分涉及哪个约束。幸运的是,这是可能的。您唯一应该知道的是,分配的顺序很重要,您可以分配多次。假设您对 a 和 b 具有唯一性约束,并且仅在涉及唯一性时才想更新 c: ... 关键更新 c = IF(a = VALUES(a) and b VALUES(b), VALUES(c), c), b = VALUES(b)
但是如果你改变了分配的顺序,if 中的第二个条件将始终为 false。
见 2。
【讨论】:
以上是关于多个 UNIQUE 字段的 ON DUPLICATE KEY UPDATE 的 MySQL 行为的主要内容,如果未能解决你的问题,请参考以下文章
postgresql----数据库表约束----UNIQUE