Pourquoi deux lignes sont-elles affectées dans mon «INSERT… ON DUPLICATE KEY UPDATE»?

89

Je fais un INSERT ... ON DUPLICATE KEY UPDATEpour un PRIMARY KEYdans le tableau suivant:

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

Cependant, même si ces valeurs doivent être uniques, je vois 2 lignes affectées.

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)

Pourquoi cela arrive-t-il?

ÉDITER

Pour comparaison, consultez cette requête:

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
la source
Pourquoi avez-vous deux clés primaires en premier lieu?
Pekka
1
@Pekka, le PRIMARY KEYest un seul pk créé sur (uid, iid)puisque la plupart des requêtes seront exécutées lorsque les deux valeurs sont connues.
Josh Smith
1
@Josh je vois. Le manuel semble cependant le décourager: In general, you should try to avoid using an ON DUPLICATE KEY UPDATE clause on tables with multiple unique indexes.faut-il que ce soit une clé primaire? Pourquoi pas un index normal?
Pekka
@Pekka, honnêtement pas sûr. Je suis encore relativement nouveau dans ce domaine. Un index a-t-il plus de sens dans ce cas?
Josh Smith
3
@Josh yup, un index normal couvrant les deux colonnes devrait fonctionner correctement ici
Pekka

Réponses:

198

À partir du manuel :

Avec ON DUPLICATE KEY UPDATE, la valeur des lignes affectées par ligne est 1 si la ligne est insérée en tant que nouvelle ligne et 2 si une ligne existante est mise à jour.

ChristopheD
la source
14
Et 0 si une ligne existante est définie sur ses valeurs actuelles.
Svish
1
@Svish, merci! Ceci est vraiment utile.
Vert
1
Je me demande simplement quelle serait la justification derrière cela ... clairement, il aurait pu être retourné comme code de réponse au lieu du nombre de lignes affectées pour le rendre moins confus
Sudip Bhandari
...: |. Existe-t-il un moyen de déterminer le nombre réel de lignes affectées? Même si une ligne existante est mise à jour, il n'y a toujours qu'une seule ligne affectée
Ulad Kasach
Est-ce la même chose pour les insertions de lots? … VALUES (2, 2, 'like'), (3, 3, 'like'), (4, 4, 'like') ON DUPLICATE …
luckydonald