Como trabalhar com loops

O Script Snowflake oferece suporte para os seguintes tipos de loops:

Este tópico explica como usar cada um desses tipos de loops.

Neste tópico:

Loop FOR

Um loop FOR repete uma sequência de passos por um número especificado de vezes ou para cada linha em um conjunto de resultados. O Script Snowflake oferece suporte para os seguintes tipos de loops FOR:

As próximas seções explicam como utilizar esses tipos de loops FOR.

Loops FOR baseados em contador

Um loop FOR baseado em contador é executado um número especificado de vezes.

A sintaxe para um loop FOR baseado no contador é

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

Por exemplo, o seguinte loop FOR é executado 5 vezes:

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;
Copy

Nota: se você estiver usando SnowSQL ou Classic Console, use este exemplo (consulte Como usar o Script Snowflake no SnowSQL e na Classic Console):

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;
$$
;
Copy

Para obter a sintaxe completa e detalhes sobre instruções FOR, consulte FOR (Script Snowflake).

Loops FOR baseados em cursor

Um loop FOR baseado em cursor itera sobre um conjunto de resultados. O número de iterações é determinado pelo número de linhas no cursor.

A sintaxe para um loop FOR baseado em cursor é:

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

O exemplo a seguir usa um loop FOR para iterar sobre as linhas em um cursor para a tabela 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;
Copy

Nota: se você estiver usando SnowSQL ou Classic Console, use este exemplo (consulte Como usar o Script Snowflake no SnowSQL e na Classic Console):

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;
$$
;
Copy

Para obter a sintaxe completa e detalhes sobre instruções FOR, consulte FOR (Script Snowflake).

Loop WHILE

Um loop WHILE itera enquanto a condição for verdadeira. Em um loop WHILE, a condição é testada imediatamente antes de executar o corpo do loop. Se a condição for falsa antes da primeira iteração, o corpo do loop não é executado nem mesmo uma vez.

A sintaxe de um loop WHILE é:

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

Por exemplo:

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

Nota: se você estiver usando SnowSQL ou Classic Console, use este exemplo (consulte Como usar o Script Snowflake no SnowSQL e na Classic Console):

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

Para obter a sintaxe completa e detalhes sobre instruções WHILE, consulte WHILE (Script Snowflake).

Loop REPEAT

Um loop REPEAT itera até uma condição ser verdadeira. Em um loop REPEAT, a condição é testada imediatamente após a execução do corpo do loop. Como resultado, o corpo do loop sempre é executado pelo menos uma vez.

A sintaxe de um loop REPEAT é:

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

Por exemplo:

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;
Copy

Nota: se você estiver usando SnowSQL ou Classic Console, use este exemplo (consulte Como usar o Script Snowflake no SnowSQL e na Classic Console):

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;
$$
;
Copy

Para obter a sintaxe completa e detalhes sobre instruções REPEAT, consulte REPEAT (Script Snowflake).

Loop LOOP

Um loop LOOP é executado até que um comando BREAK seja executado. Tal comando BREAK normalmente é incorporado dentro da lógica de ramificação (por exemplo, Instruções IF ou Instruções CASE).

A sintaxe para uma instrução LOOP é:

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

Por exemplo:

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

Nota: se você estiver usando SnowSQL ou Classic Console, use este exemplo (consulte Como usar o Script Snowflake no SnowSQL e na Classic Console):

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

Para obter a sintaxe completa e detalhes sobre instruções LOOP, consulte LOOP (Script Snowflake).

Encerramento de um loop ou iteração

Em uma construção de loop, você pode especificar quando o loop ou uma iteração do loop deve terminar mais cedo. As próximas seções explicam isso com mais detalhes:

Encerramento de um loop

Você pode encerrar explicitamente um loop antecipadamente executando o comando BREAK. BREAK (e seu sinônimo EXIT) interrompe imediatamente a iteração atual e pula quaisquer iterações restantes. Você pode pensar em BREAK como um salto para a primeira instrução executável após o final do loop.

BREAK é necessário em um LOOP, mas não é necessário em WHILE, FOR e REPEAT. Na maioria dos casos, se você tem instruções que deseja pular, você pode usar as construções de ramificação padrão (Instruções IF e Instruções CASE) para controlar quais instruções dentro de um loop serão executadas.

Um comando BREAK em si normalmente está dentro de um IF (ou CASE).

Como encerrar uma iteração sem encerrar o loop

Você pode usar o comando CONTINUE (ou ITERATE) para pular para o final de uma iteração de um loop, pulando as instruções restantes no loop. O loop continua no início da próxima iteração.

Tais saltos raramente são necessários. Na maioria dos casos, se você tem instruções que deseja pular, você pode usar as construções de ramificação padrão (Instruções IF e Instruções CASE) para controlar quais instruções dentro de um loop serão executadas.

Um comando CONTINUE ou ITERATE normalmente está dentro de um IF (ou CASE).

Como especificar onde a execução deve continuar após o término

Em um comando BREAK ou CONTINUE, se você precisar continuar a execução em um ponto específico do código (por exemplo, o loop externo em um loop aninhado), especifique uma etiqueta que identifique o ponto em que a execução deve continuar.

O exemplo a seguir demonstra isso em um loop aninhado:

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;
Copy

Nota: se você estiver usando SnowSQL ou Classic Console, use este exemplo (consulte Como usar o Script Snowflake no SnowSQL e na Classic Console):

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;
$$;
Copy

Neste exemplo:

  • Há um loop com a etiqueta INNER que está aninhado em um loop com a etiqueta OUTER.

  • CONTINUE OUTER inicia outra iteração do loop com a etiqueta OUTER.

  • BREAK OUTER encerra o loop interno e transfere o controle para o final do loop externo (com a etiqueta OUTER).

A saída desse comando é:

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

Como mostrado na saída:

  • inner_counter é incrementado até 5. CONTINUE OUTER inicia uma nova iteração do loop externo, que inicia uma nova iteração do loop interno, que incrementa esse contador até 5.

  • outer_counter nunca é incrementado. A instrução que aumenta esse contador nunca é alcançada porque BREAK OUTER transfere o controle para o final do loop externo.