10/01/2009Le message "
You can't specify target table 'nomtable' for update in FROM clause" peut s'afficher lorsqu'une requête de type UPDATE ou DELETE fait appel à une sous-requête contenant le nom de la table du FROM, typiquement comme ceci :
UPDATE matable
SET maValeur=1
WHERE id IN
(SELECT id FROM matable, matable2
WHERE matable.id=matable2.id)
Pour éviter cette erreur, il y a plusieurs solutions, dont celle de créer une table temporaire et d'y insérer le résultat de la sous-requête, puis de faire la mise à jour à partir de cette table temporaire. Voici 2 autres méthodes.
Méthode 1
En faisant en sorte que le résultat de la sous-requête soit lui-même le résultat d'une autre sous-requête, MySQL crée automatiquement une table temporaire et ne "voit" donc plus la table d'origine. Comme ceci :
UPDATE matable
SET maValeur=1
WHERE id IN
(SELECT * FROM
(SELECT id FROM matable, matable2
WHERE matable.id=matable2.id)
AS tmp)
Sur un DELETE, la requête suivante fonctionne mais peut être lente s'il y a beaucoup de données en table et tous les enregistrements de la table sont bloqués par le IN :
DELETE FROM matable
WHERE id IN
(SELECT id FROM (SELECT id FROM matable) AS tmp)
Méthode 2
La 1ère méthode ne fonctionne pas sur toutes les versions de MySQL. En voici une autre qui utilise les jointures.
Sur un UPDATE :
UPDATE matable
INNER JOIN
(SELECT id FROM matable, matable2
WHERE matable.id=matable2.id)
AS tmp
SET maValeur=1
Sur un DELETE :
DELETE matable FROM matable
JOIN (SELECT id FROM
(SELECT id FROM matable WHERE id IN (...) AS tmp)
AS tmp2 ON matable.id=tmp2.id
Cette méthode a l'avantage de ne pas bloquer les tables et d'être très rapide car elle conserve l'utilisation des index.
Dernière modification le 03/01/2019 - Quillevere.net