112

I'm doing an INSERT ... ON DUPLICATE KEY UPDATE for a PRIMARY KEY in the following table:

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    |       |
+------------+---------------------------------+------+-----+---------+-------+

However, even though these values should be unique, I'm seeing 2 rows affected.

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)

Why is this happening?

EDIT

For comparison, see this query:

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
leemes
  • 44,967
  • 21
  • 135
  • 183
Josh Smith
  • 14,674
  • 18
  • 72
  • 118
  • Why do you have two primary keys in the first place? – Pekka Sep 19 '10 at 20:28
  • 1
    @Pekka, the `PRIMARY KEY` is a single pk created on `(uid, iid)` since most queries will be run when both values are known. – Josh Smith Sep 19 '10 at 20:35
  • 1
    @Josh I see. The [manual](http://dev.mysql.com/doc/refman/5.1/en/insert-on-duplicate.html) seems to discourage it though: `In general, you should try to avoid using an ON DUPLICATE KEY UPDATE clause on tables with multiple unique indexes.` Does it need to be a primary key? Why not a normal index? – Pekka Sep 19 '10 at 20:35
  • @Pekka, honestly not sure. I'm still relatively new to this. Does an index make more sense in this case? – Josh Smith Sep 19 '10 at 20:37
  • 3
    @Josh yup, a normal index spanning both columns should would work fine here – Pekka Sep 19 '10 at 20:42
  • Pekka - To me he appears to be saying that there is indeed only one index, across both columns. (AFAIK MySQL won't allow you to declare two primary keys anyway.) – Hammerite Sep 19 '10 at 21:09

2 Answers2

246

From the manual:

With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row and 2 if an existing row is updated.

ChristopheD
  • 112,638
  • 29
  • 165
  • 179
  • 30
    And 0 if an existing row is set to its current values. – Svish Feb 03 '17 at 22:40
  • 1
    @Svish, Thanks! This is really helpful. – Green Jun 05 '17 at 00:10
  • 2
    I just wonder what would be the rationale behind it.. clearly, it could have been returned as response code instead of number of rows affected to make it less confusing – Sudip Bhandari Dec 09 '19 at 11:21
  • 1
    ... :|. Is there a way to determine the _actual_ number of rows affected? Even if an existing row is updated, there is still only _one_ row affected – Ulad Kasach Dec 23 '19 at 12:59
  • Is this the same for batch inserts as well? `… VALUES (2, 2, 'like'), (3, 3, 'like'), (4, 4, 'like') ON DUPLICATE …` – luckydonald Jun 17 '20 at 23:39
  • 1
    I wonder how many like me wasted 30 minutes trying to figure out WHICH two rows were updated...only to discover this arcane abuse of an interface. – Joseph Siefers Jan 12 '21 at 23:46
  • @Svish and on the same paragraph in the doc, there's a flag `CLIENT_FOUND_ROWS` that makes such case return 1 instead of 0 – Hoang Tran Mar 07 '21 at 07:17
8

So you know whether you updated a row (duplicate key) or just inserted one: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

ontrack
  • 2,963
  • 2
  • 15
  • 14