Question 1Si tu exécutes UPDATE stock SET qty = qty + (SELECT SUM(add_qty) FROM stock_in WHERE stock_in.sku = stock.sku); sans WHERE EXISTS (...), qu'arrive-t-il au qty des sku sans correspondance dans stock_in ?
UPDATE / DELETE avec sous-requêtes et JOIN
Sur une table stock et une table d'arrivages stock_in, apprends les mises à jour en masse via sous-requête corrélée, le UPDATE … FROM en jointure, et le DELETE conditionné par sous-requête, plus la vérification du nombre de lignes touchées — le tout en direct dans ton navigateur.
Les données qu'on utilise — stock et stock_in
Cet article couvre un style d'écriture plus avancé — mettre à jour et supprimer en s'appuyant sur les valeurs d'une autre table ou sur un résultat d'agrégation.
Précisément, trois schémas : des mises à jour dont la valeur est calculée par une sous-requête corrélée (une sous-requête dont le SELECT interne référence des colonnes de la ligne externe, donc évaluée ligne par ligne), des mises à jour en jointure via UPDATE … FROM contre une autre table, et des instructions DELETE avec une sous-requête dans la clause WHERE.
Utiliser une sous-requête corrélée pour mettre à jour avec des valeurs d'une autre table
Écrire UPDATE table SET col = (SELECT ... WHERE sous_requete.cle = table.cle) évalue le SELECT interne une fois par ligne cible et écrit le résultat dans la colonne.
Comme le SELECT interne référence une colonne de la cible externe UPDATE (stock.sku), on parle de sous-requête corrélée.
Le piège : pour les lignes de stock sans correspondance dans stock_in, le SELECT interne renvoie NULL.
-- Sans COALESCE : qty est écrasé par NULL pour les sku sans correspondance
UPDATE stock
SET qty = qty + (SELECT SUM(add_qty) FROM stock_in WHERE stock_in.sku = stock.sku);
Si tu exécutes qty = qty + (SELECT ...) tel quel, les lignes sans arrivage voient leur qty écrasé par NULL.
Pour éviter ça, soit tu enveloppes la sous-requête dans COALESCE(sous_requete, 0) pour transformer NULL en 0, soit tu restreins la cible avec WHERE EXISTS (...) pour ne toucher que les lignes ayant effectivement un arrivage.
-- D'abord prévisualise les valeurs après mise à jour avec SELECT (stock n'est pas modifié)
SELECT sku, qty,
qty + (SELECT COALESCE(SUM(add_qty), 0) FROM stock_in WHERE stock_in.sku = stock.sku) AS new_qty
FROM stock;
-- Une fois satisfait, bascule en UPDATE (COALESCE convertit NULL en 0)
UPDATE stock
SET qty = qty + (SELECT COALESCE(SUM(add_qty), 0) FROM stock_in WHERE stock_in.sku = stock.sku);
UPDATE … FROM : joindre une autre table et mettre à jour
Écrire UPDATE table SET col = valeur FROM autre_table WHERE condition_jointure te permet de joindre la cible UPDATE avec la table nommée dans FROM et de mettre à jour d'un seul coup, en référençant directement les colonnes du côté joint dans SET.
-- Exemple UPDATE … FROM : augmenter le prix de 10 uniquement pour les articles ayant un arrivage
UPDATE stock
SET price = price + 10
FROM stock_in
WHERE stock.sku = stock_in.sku;
-- Seuls les sku joints (A001 / A004) voient leur prix monter
SELECT sku, price FROM stock ORDER BY sku;
Les lignes de stock sans correspondance côté FROM (stock_in) échouent à la condition de jointure dans WHERE et sortent automatiquement de la cible de mise à jour.
Contrairement à la sous-requête corrélée, pas besoin de se prémunir séparément contre NULL.
DELETE avec condition par sous-requête, et contrôle du nombre de lignes touchées
Tu peux placer une sous-requête dans le WHERE d'un DELETE, comme DELETE FROM table WHERE col IN (SELECT ...) ou WHERE EXISTS (SELECT ...).
Ça permet des suppressions inexprimables avec une valeur fixe : « supprimer seulement les lignes présentes / absentes d'une autre table », ou « supprimer les lignes dont le résultat d'agrégat satisfait une condition ».
La suppression est destructive et irréversible, donc la pratique standard en production est de lancer d'abord le même WHERE dans un SELECT COUNT(*) pour vérifier le nombre de lignes touchées, puis de réécrire en DELETE.
Après exécution, vérifie avec SELECT COUNT(*) FROM table; pour confirmer que le nombre de lignes restantes correspond à ce que tu attendais.
-- D'abord vérifier ce qui serait supprimé : articles sous le prix moyen (stock n'est pas modifié)
SELECT sku, name, price FROM stock
WHERE price < (SELECT AVG(price) FROM stock);
-- Une fois satisfait, bascule en DELETE et vérifie le nombre restant
DELETE FROM stock
WHERE price < (SELECT AVG(price) FROM stock);
SELECT COUNT(*) AS remaining FROM stock;
Vérification des connaissances
Répondez à chaque question une par une.
Question 2Dans UPDATE stock SET qty = stock.qty + stock_in.add_qty FROM stock_in WHERE stock.sku = stock_in.sku;, comment sont traitées les lignes de stock sans correspondance dans stock_in ?
Question 3Quelle est la procédure la plus appropriée pour exécuter sûrement un DELETE piloté par sous-requête en production ?