Historique de la question :
Le SQL standard a été conçu à l'origine comme un langage déclaratif sans éléments de programmation classique (boucles, branches, accès direct), mais avec des extensions comme T-SQL/PLSQL, des constructions telles que WHILE, CASE, et même une imitation de GOTO sont devenues disponibles.
Problème :
Les opérations itératives (boucle de traitement d'enregistrements individuels) entraînent souvent un ralentissement, notamment lors du traitement de grands volumes, si on ne les remplace pas par une approche "basée sur les ensembles" (set-based). Les branches, CASE, IF — sont très pratiques, mais une imbrication excessive nuit à la lisibilité et à la prévisibilité du code.
Solution :
L'utilisation des constructions de contrôle ne doit être justifiée que lorsqu'il est impossible de se passer d'un traitement par lots (bulk/set) ! Pour des calculs complexes — un petit cycle, un trigger ou CASE est acceptable. Pour un traitement en masse — il est préférable d'utiliser des fonctions de fenêtre ou un UPDATE avec une sous-requête.
Exemple de code (T-SQL) :
DECLARE @i INT = 1 WHILE (@i <= 5) BEGIN IF @i % 2 = 0 PRINT CONCAT('Pair : ', @i) ELSE PRINT CONCAT('Impair : ', @i) SET @i = @i + 1 END
Expression CASE :
SELECT num, CASE WHEN num % 2 = 0 THEN 'pair' ELSE 'impair' END AS parité FROM numbers
Caractéristiques clés :
CASE peut-il être utilisé pour filtrer des lignes comme WHERE ?
Non ! CASE renvoie différentes valeurs, mais ne filtre pas les lignes. Une erreur fréquente consiste à "filtrer" avec CASE au lieu de WHERE, le résultat sera incorrect.
Quelle est la différence entre WHILE et CURSOR — n'est-ce pas la même chose ?
WHILE est une boucle de base, avec un contrôle utilisateur sur la variable ; CURSOR fonctionne sur les enregistrements de la table, maintenant un lien vers la ligne. CURSOR est plus gourmand en ressources et fonctionne souvent beaucoup plus lentement avec de grandes données.
Quelle approche est plus rapide pour un traitement en masse : un cycle WHILE avec UPDATE ou un seul UPDATE basé sur les ensembles ?
Dans 99% des cas, un seul UPDATE (ou INSERT) basé sur les ensembles est beaucoup plus rapide qu'une boucle sur un seul enregistrement (même si cela semble "plus flexible").
-- Mauvaise approche DECLARE @id INT = 1 WHILE (@id <= 100000) BEGIN UPDATE t SET flag=1 WHERE id=@id SET @id = @id + 1 END -- Correct UPDATE t SET flag=1 WHERE id BETWEEN 1 AND 100000
Dans un projet pour mettre à jour le statut d'un million de commandes, un cycle avec UPDATE a été écrit pour chaque id. Le traitement a duré ~8 heures. En cas d'échec à mi-parcours — tout était perdu, il fallait réparer manuellement.
Avantages :
Inconvénients :
Nous sommes passés à un UPDATE basé sur les ensembles avec une seule expression. Le temps d'exécution a été réduit à 6 minutes, le traitement est atomique.
Avantages :
Inconvénients :