为啥在我的`INSERT ... ON DUPLICATE KEY UPDATE`中有 2 行受到影响?

Posted

技术标签:

【中文标题】为啥在我的`INSERT ... ON DUPLICATE KEY UPDATE`中有 2 行受到影响?【英文标题】:Why are 2 rows affected in my `INSERT ... ON DUPLICATE KEY UPDATE`?为什么在我的`INSERT ... ON DUPLICATE KEY UPDATE`中有 2 行受到影响? 【发布时间】:2011-04-14 10:08:29 【问题描述】:

我正在为下表中的PRIMARY KEY 做一个INSERT ... ON DUPLICATE KEY UPDATE

DESCRIBE users_interests;
+------------+---------------------------------+------+-----+---------+-------+
| Field      | Type                            | Null | Key | Default | Extra |
+------------+---------------------------------+------+-----+---------+-------+
| uid        | int(11)                         | NO   | PRI | NULL    |       |
| iid        | int(11)                         | NO   | PRI | NULL    |       |
| preference | enum('like','dislike','ignore') | YES  |     | NULL    |       |
+------------+---------------------------------+------+-----+---------+-------+

但是,即使这些值应该是唯一的,我看到有 2 行受到影响。

INSERT INTO users_interests (uid, iid, preference) VALUES (2, 2, 'like')
ON DUPLICATE KEY UPDATE preference='like';
Query OK, 2 rows affected (0.04 sec)

为什么会这样?

编辑

为了比较,请看这个查询:

UPDATE users_interests SET preference='like' WHERE uid=2 AND iid=2;
Query OK, 1 row affected (0.44 sec)
Rows matched: 1  Changed: 1  Warnings: 0

【问题讨论】:

为什么一开始有两个主键? @Pekka,PRIMARY KEY 是在 (uid, iid) 上创建的单个 pk,因为大多数查询将在两个值都已知时运行。 @Josh 我明白了。 manual 似乎不鼓励它:In general, you should try to avoid using an ON DUPLICATE KEY UPDATE clause on tables with multiple unique indexes. 它需要是主键吗?为什么不是正常的索引? @Pekka,老实说不确定。我对此还是比较陌生。在这种情况下,索引是否更有意义? @Josh 是的,跨越两列的普通索引在这里应该可以正常工作 【参考方案1】:

来自the manual:

使用 ON DUPLICATE KEY UPDATE, 如果每行受影响的行值为 1 该行作为新行插入,并且 2 如果更新了现有行。

【讨论】:

如果现有行设置为当前值,则为 0。 @Svish,谢谢!这真的很有帮助。 我只是想知道它背后的基本原理是什么。显然,它可以作为响应代码而不是受影响的行数返回以减少混乱 ... :|。有没有办法确定受影响的实际行数?即使更新了现有行,仍然只有 一个 行受到影响 我想知道有多少像我一样浪费了 30 分钟试图找出更新了哪两行...只是发现了这种对界面的神秘滥用。【参考方案2】:

所以您知道您是更新了一行(重复键)还是只插入了一行:http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

【讨论】:

以上是关于为啥在我的`INSERT ... ON DUPLICATE KEY UPDATE`中有 2 行受到影响?的主要内容,如果未能解决你的问题,请参考以下文章

IDENTITY_INSERT ON不被实体框架DBSet.Add方法所尊重

为啥 $ifopt FINITEFLOAT ON 不编译?

为啥我插入 std::map 失败?

为啥我的 INSERT INTO 方法返回 false?

MS IDENTITY_INSERT 设置为 OFF [重复]

为啥我不能在 INSERT 语句中使用 WHERE 子句进一步压缩我的查询?