2009-04-27 8 views
1

Selon la documentation, joins, lorsqu'il est utilisé avec l'instruction update, fonctionne de la même manière que lorsqu'il est utilisé dans les sélections.Problème avec la mise à jour dans MySQL

Par exemple, si nous avons ces deux tableaux:

mysql> SELECT * FROM orders; 
+---------+------------+ 
| orderid | customerid | 
+---------+------------+ 
|  1 |   1 | 
|  2 |   2 | 
|  3 |   3 | 
|  4 |   1 | 
+---------+------------+ 

mysql> SELECT * FROM customers; 
+------------+------------+ 
| customerid | ordercount | 
+------------+------------+ 
|   1 |   9 | 
|   2 |   3 | 
|   3 |   8 | 
|   4 |   5 | 
|   5 |   7 | 
+------------+------------+ 

à l'aide des instructions select:

SELECT orders.customerid 
FROM orders 
JOIN customers ON (customers.customerid = orders.customerid) 

retourne:

+------------+ 
| customerid | 
+------------+ 
|   1 | 
|   1 | 
|   2 | 
|   3 | 
+------------+ 

Alors, je me attendais à la déclaration ci-dessous :

UPDATE orders 
JOIN customers ON (customers.customerid = orders.customerid) 
SET ordercount = ordercount + 1 

pour mettre à jour ordercount pour le client n ° 1 (customerid = 1) pour être 11, mais en réalité ce n'est pas le cas, voici les résultats après la mise à jour:

mysql> SELECT * FROM customers; 
+------------+------------+ 
| customerid | ordercount | 
+------------+------------+ 
|   1 |   10 | 
|   2 |   4 | 
|   3 |   9 | 
|   4 |   5 | 
|   5 |   7 | 
+------------+------------+ 

Comme vous pouvez le voir était seulement incrémenté une fois malgré qu'il se produit deux fois dans la table des commandes et malgré que l'instruction select le renvoie correctement.

Est-ce un bug dans MySQL ou est-ce que je fais quelque chose de mal? J'essaie d'éviter d'utiliser le groupe pour des raisons de performance, d'où mon intérêt à comprendre ce qui se passe.

Merci à l'avance

+0

pourrait-il que ce problème montre indirectement une faille dans la conception de votre db? peut-être que c'est trop difficile de garder une commande. Cela peut entraîner des incohérences si vous ajustez ces scores par des mises à jour indépendantes. peut-être qu'il serait préférable de générer ce compte avec une requête, quand vous en avez besoin. – markus

+0

J'ai seulement utilisé l'exemple des clients et des commandes pour démontrer le problème, je ne vais pas l'utiliser de cette façon –

Répondre

2

Oui, MySQL met à jour chaque enregistrement d'une table jointe au plus une fois.

Je ne le trouve pas dans la documentation, mais la pratique l'indique.

Je vais probablement l'afficher comme un bug, donc ils ont au moins l'ajouter à la documentation:

CREATE TABLE updater (value INT NOT NULL); 

INSERT 
INTO updater 
VALUES (1); 

SELECT * 
FROM updater; 

value 
--- 
1 

UPDATE updater u 
JOIN (
     SELECT 1 AS newval 
     UNION ALL 
     SELECT 2 
     ) q 
SET  u.value = u.value + newval; 

SELECT * 
FROM updater; 

value 
--- 
2 

(expected 4). 

SQL Server, par ailleurs, se comporte même dans une table multiple UPDATE.

Vous pouvez utiliser:

UPDATE orders o 
SET  ordercount = ordercount + 
     (
     SELECT COUNT(*) 
     FROM customers c 
     WHERE c.customerid = o.customerid 
     ) 

qui est la même sur les performances aussi longtemps que vous avez un index sur customers (customer_id)

+0

Alors, est-ce par conception? La documentation ne dit rien à ce sujet –

+0

Désolé de ne pas mentionner cela dans la question mais en fait j'ai plus de critères dans la déclaration de jointure que j'ai retirée pour simplifier les choses .. ce code dans votre réponse mettra à jour toute la table ce qui n'est pas ce que je veux, les clients peuvent avoir un grand nombre d'enregistrements (ce n'est pas une table clients en passant, qui servait uniquement à démontrer le problème), les résultats de jointure ne sont que quelques enregistrements à mettre à jour –

+0

répondre .. en fait, je n'utilise que quelques enregistrements dans les commandes (en utilisant certains critères) pour mettre à jour la table des clients .. semble que l'utilisation de GROUP BY est la seule façon –

Questions connexes