Travailler avec des boucles

Exécution de scripts Snowflake prend en charge les types de boucles suivants :

Cette rubrique explique comment utiliser chacun de ces types de boucles.

Dans ce chapitre :

Boucle FOR

Une boucle FOR répète une séquence d’étapes pour un nombre spécifié de fois ou pour chaque ligne d’un jeu de résultats. Exécution de scripts Snowflake prend en charge les types suivants de boucles FOR :

Les sections suivantes expliquent comment utiliser ces types de boucles FOR.

Boucles FOR basées sur le compteur

Une boucle FOR basée sur un compteur s’exécute un nombre déterminé de fois.

La syntaxe d’une boucle FOR basée sur un compteur est la suivante

FOR <counter_variable> IN [ REVERSE ] <start> TO <end> { DO | LOOP }
  <statement>;
  [ <statement>; ... ]
END { FOR | LOOP } [ <label> ] ;

Par exemple, la boucle suivante FOR s’exécute 5 fois :

DECLARE
  counter INTEGER DEFAULT 0;
  maximum_count INTEGER default 5;
BEGIN
  FOR i IN 1 TO maximum_count DO
    counter := counter + 1;
  END FOR;
  RETURN counter;
END;

Remarque : si vous utilisez SnowSQL ou l’interface Web classique, utilisez cet exemple à la place (voir Utilisation d’Exécution de scripts Snowflake dans SnowSQL et l’interface Web classique) :

EXECUTE IMMEDIATE $$
DECLARE
  counter INTEGER DEFAULT 0;
  maximum_count INTEGER default 5;
BEGIN
  FOR i IN 1 TO maximum_count DO
    counter := counter + 1;
  END FOR;
  RETURN counter;
END;
$$
;

Pour une syntaxe complète et des détails sur les instructions FOR, voir FOR.

Boucles FOR basées sur le curseur

Une boucle basée sur un curseur FOR itère sur un jeu de résultats. Le nombre d’itérations est déterminé par le nombre de lignes dans le curseur.

La syntaxe d’une boucle FOR basée sur le curseur est la suivante :

FOR <row_variable> IN <cursor_name> DO
  <statement>;
[ <statement>; ... ]
END FOR [ <label> ] ;

L’exemple suivant utilise une boucle FOR pour itérer sur les lignes d’un curseur pour la table invoices :

CREATE OR REPLACE TABLE invoices (price NUMBER(12, 2));
INSERT INTO invoices (price) VALUES
  (11.11),
  (22.22);

DECLARE
  total_price FLOAT;
  c1 CURSOR FOR select price from invoices;
BEGIN
  total_price := 0.0;
  FOR record IN c1 DO
    total_price := total_price + record.price;
  END FOR;
  RETURN total_price;
END;

Remarque : si vous utilisez SnowSQL ou l’interface Web classique, utilisez cet exemple à la place (voir Utilisation d’Exécution de scripts Snowflake dans SnowSQL et l’interface Web classique) :

CREATE OR REPLACE TABLE invoices (price NUMBER(12, 2));
INSERT INTO invoices (price) VALUES
  (11.11),
  (22.22);

EXECUTE IMMEDIATE $$
DECLARE
  total_price FLOAT;
  c1 CURSOR FOR select price from invoices;
BEGIN
  total_price := 0.0;
  FOR record IN c1 DO
    total_price := total_price + record.price;
  END FOR;
  RETURN total_price;
END;
$$
;

Pour une syntaxe complète et des détails sur les instructions FOR, voir FOR.

Boucle WHILE

Une boucle WHILE itère pendant qu’une condition est vraie. Dans une boucle WHILE, la condition est testée immédiatement avant l’exécution du corps de la boucle. Si la condition est fausse avant la première itération, le corps de la boucle ne s’exécute pas une seule fois.

La syntaxe d’une boucle WHILE est la suivante :

WHILE ( <condition> ) { DO | LOOP }
  <statement>;
  [ <statement>; ... ]
END { WHILE | LOOP } [ <label> ] ;

Par exemple :

BEGIN
  LET counter := 0;
  WHILE (counter < 5) DO
    counter := counter + 1;
  END WHILE;
  RETURN counter;
END;

Remarque : si vous utilisez SnowSQL ou l’interface Web classique, utilisez cet exemple à la place (voir Utilisation d’Exécution de scripts Snowflake dans SnowSQL et l’interface Web classique) :

EXECUTE IMMEDIATE $$
BEGIN
  LET counter := 0;
  WHILE (counter < 5) DO
    counter := counter + 1;
  END WHILE;
  RETURN counter;
END;
$$
;

Pour une syntaxe complète et des détails sur les instructions WHILE, voir WHILE.

Boucle REPEAT

Une boucle REPEAT itère jusqu’à ce qu’une condition soit vraie. Dans une boucle REPEAT, la condition est testée immédiatement après l’exécution du corps de la boucle. Par conséquent, le corps de la boucle s’exécute toujours au moins une fois.

La syntaxe d’une boucle REPEAT est la suivante :

REPEAT
  <statement>;
  [ <statement>; ... ]
UNTIL ( <condition> )
END REPEAT [ <label> ] ;

Par exemple :

BEGIN
  LET counter := 5;
  LET number_of_iterations := 0;
  REPEAT
    counter := counter - 1;
    number_of_iterations := number_of_iterations + 1;
  UNTIL (counter = 0)
  END REPEAT;
  RETURN number_of_iterations;
END;

Remarque : si vous utilisez SnowSQL ou l’interface Web classique, utilisez cet exemple à la place (voir Utilisation d’Exécution de scripts Snowflake dans SnowSQL et l’interface Web classique) :

EXECUTE IMMEDIATE $$
BEGIN
  LET counter := 5;
  LET number_of_iterations := 0;
  REPEAT
    counter := counter - 1;
    number_of_iterations := number_of_iterations + 1;
  UNTIL (counter = 0)
  END REPEAT;
  RETURN number_of_iterations;
END;
$$
;

Pour une syntaxe complète et des détails sur les instructions REPEAT, voir REPEAT.

Boucle LOOP

Une boucle LOOP s’exécute jusqu’à ce qu’une commande BREAK soit exécutée. Une telle commande BREAK est normalement intégrée dans une logique « branching » (par exemple, Instructions IF ou Instructions CASE).

La syntaxe d’une instruction LOOP est la suivante :

LOOP
  <statement>;
  [ <statement>; ... ]
END LOOP [ <label> ] ;

Par exemple :

BEGIN
  LET counter := 5;
  LOOP
    IF (counter = 0) THEN
      BREAK;
    END IF;
    counter := counter - 1;
  END LOOP;
  RETURN counter;
END;

Remarque : si vous utilisez SnowSQL ou l’interface Web classique, utilisez cet exemple à la place (voir Utilisation d’Exécution de scripts Snowflake dans SnowSQL et l’interface Web classique) :

EXECUTE IMMEDIATE $$
BEGIN
  LET counter := 5;
  LOOP
    IF (counter = 0) THEN
      BREAK;
    END IF;
    counter := counter - 1;
  END LOOP;
  RETURN counter;
END;
$$
;

Pour une syntaxe complète et des détails sur les instructions LOOP, voir LOOP.

Mettre fin à une boucle ou une itération

Dans une construction de boucle, vous pouvez spécifier quand la boucle ou une itération de la boucle doit se terminer prématurément. Les sections suivantes expliquent cela plus en détail :

Terminer une boucle

Vous pouvez explicitement mettre fin à une boucle de manière anticipée en exécutant la commande BREAK. BREAK (et son synonyme EXIT) arrête immédiatement l’itération en cours, et saute toutes les itérations restantes. Vous pouvez considérer BREAK comme un saut à la première instruction exécutable après la fin de la boucle.

BREAK est nécessaire dans une LOOP mais ne l’est pas dans WHILE, FOR et dans REPEAT. Dans la plupart des cas, si vous souhaitez sauter des instructions, vous pouvez utiliser les constructions « branching » standard (Instructions IF et Instructions CASE) pour contrôler les instructions exécutées dans une boucle.

Une commande BREAK elle-même se trouve généralement à l’intérieur d’une instruction IF (ou CASE).

Terminer une itération sans terminer la boucle

Vous pouvez utiliser la commande CONTINUE (ou ITERATE) pour sauter à la fin d’une itération d’une boucle, en ignorant les instructions restantes de la boucle. La boucle se poursuit au début de l’itération suivante.

De tels sauts sont rarement nécessaires. Dans la plupart des cas, si vous souhaitez sauter des instructions, vous pouvez utiliser les constructions « branching » standard (Instructions IF et Instructions CASE) pour contrôler les instructions exécutées dans une boucle.

Une commande CONTINUE ou ITERATE se trouve généralement à l’intérieur d’une instruction IF (ou CASE).

Spécifier l’endroit où l’exécution doit se poursuivre après la fin de l’opération

Dans une commande BREAK ou CONTINUE, si vous devez poursuivre l’exécution à un point spécifique du code (par exemple, la boucle extérieure d’une boucle imbriquée), spécifiez une étiquette qui identifie le point auquel l’exécution doit se poursuivre.

L’exemple suivant en fait la démonstration dans une boucle imbriquée :

BEGIN
  LET inner_counter := 0;
  LET outer_counter := 0;
  LOOP
    LOOP
      IF (inner_counter < 5) THEN
        inner_counter := inner_counter + 1;
        CONTINUE OUTER;
      ELSE
        BREAK OUTER;
      END IF;
    END LOOP INNER;
    outer_counter := outer_counter + 1;
    BREAK;
  END LOOP OUTER;
  RETURN array_construct(outer_counter, inner_counter);
END;

Remarque : si vous utilisez SnowSQL ou l’interface Web classique, utilisez cet exemple à la place (voir Utilisation d’Exécution de scripts Snowflake dans SnowSQL et l’interface Web classique) :

EXECUTE IMMEDIATE $$
BEGIN
  LET inner_counter := 0;
  LET outer_counter := 0;
  LOOP
    LOOP
      IF (inner_counter < 5) THEN
        inner_counter := inner_counter + 1;
        CONTINUE OUTER;
      ELSE
        BREAK OUTER;
      END IF;
    END LOOP INNER;
    outer_counter := outer_counter + 1;
    BREAK;
  END LOOP OUTER;
  RETURN array_construct(outer_counter, inner_counter);
END;
$$;

Dans cet exemple :

  • Il existe une boucle étiquetée INNER qui est imbriquée dans une boucle étiquetée OUTER.

  • CONTINUE OUTER lance une autre itération de la boucle avec l’étiquette OUTER.

  • BREAK OUTER termine la boucle intérieure et transfère le contrôle à la fin de la boucle extérieure (étiquetée OUTER).

La sortie de cette commande est la suivante :

+-----------------+
| anonymous block |
|-----------------|
| [               |
|   0,            |
|   5             |
| ]               |
+-----------------+

Comme indiqué dans la sortie :

  • inner_counter est incrémenté jusqu’à 5. CONTINUE OUTER lance une nouvelle itération de la boucle externe, qui lance une nouvelle itération de la boucle interne, qui incrémente ce compteur jusqu’à 5.

  • outer_counter n’est jamais incrémenté. L’instruction qui incrémente ce compteur n’est jamais atteinte car BREAK OUTER transfère le contrôle à la fin de la boucle externe.

Revenir au début