Por que 2 linhas são afetadas em meu `INSERT ... ON DUPLICATE KEY UPDATE`?

89

Estou fazendo um INSERT ... ON DUPLICATE KEY UPDATEfor a PRIMARY KEYna seguinte tabela:

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

No entanto, embora esses valores devam ser exclusivos, estou vendo 2 linhas afetadas.

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)

Por que isso está acontecendo?

EDITAR

Para comparação, consulte esta consulta:

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
Josh Smith
fonte
Por que você tem duas chaves primárias em primeiro lugar?
Pekka
1
@Pekka, PRIMARY KEYé um único pk criado em (uid, iid)uma vez que a maioria das consultas será executada quando ambos os valores forem conhecidos.
Josh Smith
1
@Josh entendo. O manual parece desencorajá-lo: In general, you should try to avoid using an ON DUPLICATE KEY UPDATE clause on tables with multiple unique indexes.ela precisa ser uma chave primária? Por que não um índice normal?
Pekka
@Pekka, honestamente não tenho certeza. Ainda sou relativamente novo nisso. Um índice faz mais sentido neste caso?
Josh Smith
3
@Josh yup, um índice normal abrangendo ambas as colunas funcionaria bem aqui
Pekka,

Respostas:

198

Do manual :

Com ON DUPLICATE KEY UPDATE, o valor das linhas afetadas por linha é 1 se a linha for inserida como uma nova linha e 2 se uma linha existente for atualizada.

ChristopheD
fonte
14
E 0 se uma linha existente for definida com seus valores atuais.
Svish
1
@Svish, obrigado! Isso é realmente útil.
Verde de
1
Eu só me pergunto qual seria a razão por trás disso .. claramente, ele poderia ter sido retornado como código de resposta em vez do número de linhas afetadas para torná-lo menos confuso
Sudip Bhandari
...: |. Existe uma maneira de determinar o número real de linhas afetadas? Mesmo se uma linha existente for atualizada, ainda há apenas uma linha afetada
Ulad Kasach
É o mesmo para inserções de lote também? … VALUES (2, 2, 'like'), (3, 3, 'like'), (4, 4, 'like') ON DUPLICATE …
luckydonald