web-dev-qa-db-fra.com

Faire la boucle while dans SQL Server 2008

Existe-t-il une méthode pour implémenter la boucle do while dans SQL Server 2008?

113
Nithesh

Je ne suis pas sûr de DO-WHILE DANS MS SQL Server 2008, mais vous pouvez modifier la logique de votre boucle WHILE afin de l'utiliser comme une boucle DO-WHILE.

Les exemples sont pris ici: http://blog.sqlauthority.com/2007/10/24/sql-server-simple-example-of-while-loop-with-continue-and-and-break-keywords/

  1. Exemple de boucle WHILE

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
    END
    GO
    

    ResultSet:

    1
    2
    3
    4
    5
    
  2. Exemple de mot clé WHILE Loop avec BREAK

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
        IF @intFlag = 4
            BREAK;
    END
    GO
    

    ResultSet:

    1
    2
    3
    
  3. Exemple de boucle WHILE avec les mots clés CONTINUE et BREAK

    DECLARE @intFlag INT
    SET @intFlag = 1
    WHILE (@intFlag <=5)
    BEGIN
        PRINT @intFlag
        SET @intFlag = @intFlag + 1
        CONTINUE;
        IF @intFlag = 4 -- This will never executed
            BREAK;
    END
    GO
    

    ResultSet:

    1
    2
    3
    4
    5
    

Mais essayez de éviter les boucles au niveau de la base de données . Référence .

176
Pratik

Si le mot clé GOTO ne vous choque pas beaucoup, vous pouvez l'utiliser pour simuler une variable DO/WHILE dans T-SQL. Prenons l'exemple suivant, plutôt absurde, écrit en pseudocode:

SET I=1
DO
 PRINT I
 SET I=I+1
WHILE I<=10

Voici le code T-SQL équivalent utilisant goto:

DECLARE @I INT=1;
START:                -- DO
  PRINT @I;
  SET @I+=1;
IF @I<=10 GOTO START; -- WHILE @I<=10

Notez le mappage un à un entre la solution activée GOTO et le pseudocode DO/WHILE d'origine. Une implémentation similaire utilisant une boucle WHILE ressemblerait à ceci:

DECLARE @I INT=1;
WHILE (1=1)              -- DO
 BEGIN
  PRINT @I;
  SET @I+=1;
  IF NOT (@I<=10) BREAK; -- WHILE @I<=10
 END

Maintenant, vous pouvez bien sûr réécrire cet exemple particulier sous la forme d'une simple boucle WHILE, car ce n'est pas un si bon candidat pour une construction DO/WHILE. L'accent a été mis sur l'exemple de la brièveté plutôt que sur l'applicabilité, car les cas légitimes nécessitant une variable DO/WHILE sont rares.


REPEAT/UNTIL, n'importe qui (ne fonctionne pas dans T-SQL)?

SET I=1
REPEAT
  PRINT I
  SET I=I+1
UNTIL I>10

... et la solution basée sur GOTO dans T-SQL:

DECLARE @I INT=1;
START:                    -- REPEAT
  PRINT @I;
  SET @I+=1;
IF NOT(@I>10) GOTO START; -- UNTIL @I>10

Grâce à l'utilisation créative de GOTO et à l'inversion logique via le mot clé NOT, il existe une relation très étroite entre le pseudocode d'origine et la solution basée sur GOTO. Une solution similaire utilisant une boucle WHILE ressemble à ceci:

DECLARE @I INT=1;
WHILE (1=1)       -- REPEAT
 BEGIN
  PRINT @I;
  SET @I+=1;
  IF @I>10 BREAK; -- UNTIL @I>10
 END

On peut faire valoir que, dans le cas de la variable REPEAT/UNTIL, la solution basée sur WHILE est plus simple, car la condition if n'est pas inversée. D'autre part, il est également plus verbeux.

Sans le dédain que suscite l'utilisation de GOTO, il pourrait même s'agir de solutions idiomatiques pour les rares fois où ces constructions de boucle (diaboliques) sont nécessaires dans le code T-SQL par souci de clarté.

Utilisez-les à votre propre discrétion, en essayant de ne pas subir la colère de vos collègues développeurs quand ils vous attrapent en utilisant la très décriée GOTO.

57
Michael Goldshteyn

Il me semble me rappeler avoir lu cet article plusieurs fois et la réponse n’est que proche de ce dont j’ai besoin.

Habituellement, lorsque je pense que je vais avoir besoin d’un DO WHILE dans T-SQL, c’est parce que j’itère un curseur, et je recherche en grande partie une clarté optimale (par rapport à une vitesse optimale). Dans T-SQL, cela semble correspondre à un WHILE TRUE/IF BREAK.

Si c'est le scénario qui vous a amené ici, cet extrait peut vous faire gagner un moment. Sinon, bon retour, moi. Maintenant, je peux être certain que j'ai été ici plus d'une fois. :)

DECLARE Id INT, @Title VARCHAR(50)
DECLARE Iterator CURSOR FORWARD_ONLY FOR
SELECT Id, Title FROM dbo.SourceTable
OPEN Iterator
WHILE 1=1 BEGIN
    FETCH NEXT FROM @InputTable INTO @Id, @Title
    IF @@FETCH_STATUS < 0 BREAK
    PRINT 'Do something with ' + @Title
END
CLOSE Iterator
DEALLOCATE Iterator

Malheureusement, T-SQL ne semble pas offrir un moyen plus propre de définir séparément le fonctionnement de la boucle que cette boucle infinie.

18
shannon

Vous pouvez également utiliser une variable de sortie si vous voulez que votre code soit un peu plus lisible:

DECLARE @Flag int = 0
DECLARE @Done bit = 0

WHILE @Done = 0 BEGIN
    SET @Flag = @Flag + 1
    PRINT @Flag
    IF @Flag >= 5 SET @Done = 1
END

Cela serait probablement plus pertinent si vous avez une boucle plus compliquée et essayez de suivre la logique. Comme indiqué, les boucles sont chères alors essayez d’utiliser d’autres méthodes si vous le pouvez.

4
Sebris87

Seule la boucle While est officiellement prise en charge par le serveur SQL. Il y a déjà réponse pour faire en boucle. Je détaille la réponse sur les moyens de réaliser différents types de boucles dans SQL Server.

Si vous savez, vous devez quand même terminer la première itération de la boucle, vous pouvez essayer la version DO..WHILE ou REPEAT..UNTIL de SQL Server.

DO..WHILE Loop

DECLARE @X INT=1;

WAY:  --> Here the  DO statement

  PRINT @X;

  SET @X += 1;

IF @X<=10 GOTO WAY;

Boucle REPEAT..UNTIL

DECLARE @X INT = 1;

WAY:  -- Here the REPEAT statement

  PRINT @X;

  SET @X += 1;

IFNOT(@X > 10) GOTO WAY;

FOR Loop

DECLARE @cnt INT = 0;

WHILE @cnt < 10
BEGIN
   PRINT 'Inside FOR LOOP';
   SET @cnt = @cnt + 1;
END;

PRINT 'Done FOR LOOP';

Référence

0
Somnath Muluk