Une sous-requête est un moyen puissant de trouver les données que vous souhaitez utiliser pour une autre requête. Ils sont souvent utilisés dans les instructions SELECT et UPDATE pour rendre ces requêtes plus efficaces et plus faciles à gérer.
Il existe plusieurs manières d'utiliser les sous-requêtes dans les instructions UPDATE. Jetons un coup d'œil à chacun d'eux.
SET et sous-requête
La première méthode que nous allons examiner consiste à utiliser une sous-requête dans la clause SET d'une instruction UPDATE.
Disons que nous avions un tableau de produits qui ressemblait à ceci :
[identifiant de table=29 /]
Il stocke quelques informations sur différents produits vendus par une entreprise.
Supposons que l'entreprise décide d'augmenter le prix du produit "Couch" (identifiant de produit 1). Cependant, au lieu de fixer un prix spécifique, ils souhaitent le rendre 20 % plus élevé que le produit le plus cher dont ils disposent.
Pour ce faire, nous pouvons utiliser une sous-requête dans la clause SET. Nous pourrions utiliser des instructions séparées, mais il est plus facile de maintenir l'utilisation d'une seule instruction.
Notre déclaration ressemblerait à ceci :
UPDATE product SET price = ( SELECT MAX(price) * 1.2 FROM product ) WHERE product_id = 1;
Vous pouvez voir que la clause SET inclut une sous-requête, qui trouve la valeur MAX de la colonne de prix dans la table des produits et la multiplie par 1,2 pour ajouter 20 %. Enfin, la clause WHERE est en dehors de la sous-requête pour ne mettre à jour que le product_id de 1, car elle s'applique à UPDATE plutôt qu'à la sous-requête.
Cela entraînera le changement suivant :
[identifiant de table=30 /]
SET et sous-requête corrélée
Une autre façon d'utiliser une sous-requête dans une instruction UPDATE consiste à utiliser une sous-requête corrélée.
Il fonctionne de manière similaire à l'exemple précédent. Cependant, une sous-requête corrélée est une sous-requête qui fait référence à l'instruction externe et peut faire partie d'une instruction UPDATE.
En utilisant les données de l'exemple précédent (la table des produits), l'entreprise souhaite désactiver tous les produits pour lesquels aucune commande n'a été passée. Les données pour cela sont stockées dans la table order_line.
Si nous l'écrivons en tant que sous-requête corrélée, la requête ressemblera à ceci :
UPDATE product p SET active = ( SELECT CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE 'N' END FROM order_line o WHERE o.product_id = p.product_id );
La sous-requête exécutera une fonction COUNT à l'aide d'une instruction CASE pour déterminer si la valeur renvoyée est Y ou N en fonction de la valeur de COUNT. Il est calculé pour chaque product_id et correspond à la requête externe.
Cela se traduira par la colonne active pour certains produits définis sur Y et d'autres sur N :
[identifiant de table=31 /]
Sous-requête WHERE supérieure à
Il est également possible d'utiliser une sous-requête dans la clause WHERE. Tout comme dans les exemples précédents, cela peut être fait pour supprimer l'étape distincte de recherche d'une valeur à mettre à jour, puis pour exécuter la requête pour la mettre à jour.
Nous pouvons continuer à travailler avec notre exemple des étapes précédentes. Supposons que l'entreprise souhaite activer des produits dont le prix est supérieur à la moyenne. Pour ce faire, nous pouvons ajouter une sous-requête à la clause WHERE.
Tout d'abord, désactivez tous les produits.
UPDATE product SET active = ’N’;
Ensuite, mettez à jour la table à l'aide de notre sous-requête.
UPDATE product SET active = 'Y' WHERE price > ( SELECT AVG(price) FROM product );
Cela définira la valeur active sur Y pour tous les enregistrements dont le prix est supérieur à la moyenne.
Le tableau ressemble maintenant à ceci :
[identifiant de table=32 /]
Il affiche 2 enregistrements avec une valeur active de Y car ils sont supérieurs à la moyenne.
Ce type de requête peut également être exécuté avec d'autres opérateurs qui autorisent une seule valeur, tels que
Sous-requête WHERE IN
De plus, nous pouvons utiliser une sous-requête avec un opérateur IN dans la clause WHERE.
Ceci est similaire à l'exemple précédent qui utilisait l'opérateur supérieur à pour une seule valeur. L'opérateur IN peut être appliqué à plusieurs valeurs.
Disons que l'entreprise souhaitait mettre à jour le prix de certains produits qui étaient le seul article de la catégorie. Les prix devraient être divisés par deux.
Notre requête pourrait ressembler à ceci :
UPDATE product SET price = price / 2 WHERE category_id IN ( SELECT category_id FROM product GROUP BY category_id HAVING COUNT(*) = 1 );
La sous-requête trouve toutes les valeurs category_id où COUNT est 1. Nous n'avons pas besoin d'avoir COUNT dans la partie SELECT de la sous-requête, cependant, si nous le faisons, la requête affichera une erreur.
L'instruction UPDATE mettra à jour le prix lorsque la catégorie répond aux critères de la sous-requête.
Nos résultats ressembleront alors à ceci :
[identifiant de table=33 /]
Les données semblent très similaires. Cependant, le produit avec un ID de catégorie de 1 a vu son prix mis à jour à la moitié de son coût d'origine, car il s'agit du seul produit de sa catégorie.
Sous-requête UPDATE
Enfin, vous pouvez utiliser une sous-requête dans une instruction UPDATE pour que la table soit mise à jour.
Dans les exemples précédents, nous venons d'utiliser la table des produits. Cependant, vous pouvez utiliser une sous-requête au lieu de la table des produits, qui renverra un ensemble de résultats pouvant être mis à jour.
Le jeu de résultats doit pouvoir être mis à jour, comme dans le cas où vous créez un objet VIEW et essayez de le mettre à jour. Il doit être simple et avoir la clé primaire.
Ainsi, en utilisant nos exemples précédents, supposons que l'entreprise souhaite changer la catégorie pour tous les produits de la catégorie 4 à la catégorie 5.
Notre requête pourrait ressembler à ceci :
UPDATE ( SELECT product_id, category_id FROM product) SET category_id = 5 WHERE category_id = 4;
C'est un exemple simple qui illustre le concept. Le tableau a été remplacé par l'instruction SELECT qui n'affiche que deux colonnes du tableau.
Les résultats de cette requête seraient :
[identifiant de table=34 /]
Le même résultat pourrait être obtenu en déplaçant la clause WHERE vers l'instruction UPDATE :
UPDATE ( SELECT product_id, category_id FROM product WHERE category_id = 4) SET category_id = 5;
Conclusion
L'utilisation d'une sous-requête dans une instruction UPDATE peut être un bon moyen d'améliorer la maintenabilité de vos requêtes. Il peut également réduire le nombre d'étapes nécessaires pour mettre à jour vos données en compressant deux requêtes ou plus en une seule requête.