Numeric Loops em Oracle PL/SQL
Olá, aluno! Hoje vamos mergulhar no fascinante mundo dos Numeric Loops em Oracle PL/SQL. Prepare-se para uma jornada de aprendizado que vai te transformar em um expert nesse assunto.
Objetivos desse Artigo
Após esta leitura, você será capaz de:
- Usar Numeric FOR Loops com a opção IN
- Usar Numeric FOR Loops com a opção REVERSE
- Usar Controles de Iteração com Numeric FOR Loops
- Terminar Numeric FOR Loops prematuramente
Estrutura Básica do Numeric FOR Loop
Vamos começar entendendo a estrutura básica de um Numeric FOR Loop. Imagine que você está contando os degraus de uma escada. O Numeric FOR Loop seria como contar esses degraus de forma automática.
A estrutura básica é a seguinte:
1 2 3 4 5 6 |
FOR contador_loop IN [REVERSE] limite_inferior..limite_superior LOOP instrução_1; instrução_2; ... instrução_n; END LOOP; |
Vamos analisar cada parte:
- FOR: Palavra-chave que inicia nosso loop.
- contador_loop: Variável de índice definida implicitamente.
- IN [REVERSE]: Especifica a direção da contagem.
- limite_inferior..limite_superior: Define o intervalo de iterações.
- LOOP: Marca o início do bloco de código a ser repetido.
- instruções: Ações que queremos executar repetidamente.
- END LOOP: Marca o fim do nosso bloco de código.
Usando a Opção IN no Loop
Vamos ver um exemplo prático:
1 2 3 4 5 |
BEGIN FOR v_contador IN 1..5 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); END LOOP; END; |
Este código produzirá:
1 2 3 4 5 6 |
v_contador = 1 v_contador = 2 v_contador = 3 v_contador = 4 v_contador = 5 |
Importante: O contador do loop é incrementado automaticamente. Não tente incrementá-lo manualmente dentro do loop!
Usando a Opção REVERSE no Loop
Agora, vamos contar de trás para frente:
1 2 3 4 5 |
BEGIN FOR v_contador IN REVERSE 1..5 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); END LOOP; END; |
Este código produzirá:
1 2 3 4 5 6 |
v_contador = 5 v_contador = 4 v_contador = 3 v_contador = 2 v_contador = 1 |
Controles de Iteração Avançados (Oracle 21c)
Com o Oracle 21c, temos opções mais avançadas de controle de iteração:
1. Iteração com Passo Personalizado
1 2 3 4 5 |
BEGIN FOR v_contador IN 1..10 BY 2 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); END LOOP; END; |
Resultado:
1 2 3 4 5 6 |
v_contador = 1 v_contador = 3 v_contador = 5 v_contador = 7 v_contador = 9 |
2. Iteração com Números Fracionários
1 2 3 4 5 |
BEGIN FOR v_contador NUMBER(3, 1) IN 1.5..10.5 BY 2.5 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); END LOOP; END; |
3. Iteração com Condição WHEN
1 2 3 4 5 |
BEGIN FOR v_contador IN 1..10 WHEN MOD(v_contador, 2) = 0 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); END LOOP; END; |
Este loop só executará para números pares.
4. Iteração de Expressão Única
No Oracle 21c, uma iteração de expressão única pode ser escrita de forma mais concisa:
1 2 3 4 5 6 7 8 |
DECLARE v_contador NUMBER; BEGIN FOR v_contador IN 1, REPEAT v_contador + 3 WHILE v_contador <= 10 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); END LOOP; END; / |
Vamos quebrar isso em partes:
DECLARE v_contador NUMBER;
- Aqui, estamos declarando a variável
v_contador
como um NUMBER. Embora o loop FOR declare implicitamente a variável de loop, é uma boa prática declará-la explicitamente para maior clareza.
- Aqui, estamos declarando a variável
FOR v_contador IN 1, REPEAT v_contador + 3 WHILE v_contador <= 10 LOOP
- Esta é a linha-chave que utiliza a nova sintaxe do Oracle 21c para loops FOR.
IN 1
: Define o valor inicial dev_contador
como 1.REPEAT v_contador + 3
: Especifica comov_contador
deve ser atualizado após cada iteração. Neste caso, ele será incrementado em 3 a cada loop.WHILE v_contador <= 10
: Define a condição de continuação do loop. O loop continuará enquantov_contador
for menor ou igual a 10.
DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador);
- Esta linha imprime o valor atual de
v_contador
em cada iteração do loop.
- Esta linha imprime o valor atual de
Agora, vamos ver como o loop se comporta:
- Primeira iteração:
v_contador
= 1- Imprime: v_contador = 1
- Próximo valor: 1 + 3 = 4
- Segunda iteração:
v_contador
= 4- Imprime: v_contador = 4
- Próximo valor: 4 + 3 = 7
- Terceira iteração:
v_contador
= 7- Imprime: v_contador = 7
- Próximo valor: 7 + 3 = 10
- Quarta iteração:
v_contador
= 10- Imprime: v_contador = 10
- Próximo valor seria 13, mas como 13 > 10, o loop termina aqui.
Portanto, a saída deste código será:
1 2 3 4 |
v_contador = 1 v_contador = 4 v_contador = 7 v_contador = 10 |
Esta nova sintaxe do Oracle 21c permite uma forma mais concisa e expressiva de escrever loops com incrementos personalizados e condições de parada, tudo em uma única linha. Ela combina a inicialização, a regra de incremento e a condição de parada em uma estrutura única e coesa.
Para versões anteriores do Oracle, você precisaria usar uma abordagem diferente, como esta:
1 2 3 4 5 6 7 8 9 |
DECLARE v_contador NUMBER := 1; BEGIN WHILE v_contador <= 10 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); v_contador := v_contador + 3; END LOOP; END; / |
Vamos comparar as duas versões do código e destacar as principais diferenças entre a abordagem tradicional (antes do Oracle 21c) e a nova sintaxe introduzida no Oracle 21c.
Tipo de Loop:
- Antes: Usa um loop WHILE.
- 21c: Usa um loop FOR com sintaxe estendida.
Inicialização da variável:
- Antes:
v_contador NUMBER := 1;
(inicialização explícita na declaração) - 21c:
v_contador NUMBER;
(inicialização implícita no loop FOR)
Estrutura do loop:
Antes:
1 2 3 4 |
WHILE v_contador <= 10 LOOP -- código v_contador := v_contador + 3; END LOOP; |
Com 21c:
1 2 3 |
FOR v_contador IN 1, REPEAT v_contador + 3 WHILE v_contador <= 10 LOOP -- código END LOOP; |
Controle de incremento:
- Antes: Incremento explícito dentro do loop (
v_contador := v_contador + 3;
) - 21c: Incremento definido na cláusula REPEAT do FOR (
REPEAT v_contador + 3
)
Condição de parada:
- Antes: Definida no início do loop WHILE (
WHILE v_contador <= 10
) - 21c: Definida na cláusula WHILE do FOR (
WHILE v_contador <= 10
)
Legibilidade e concisão:
- Antes: Lógica de inicialização, incremento e condição de parada separadas.
- 21c: Toda a lógica de controle do loop está em uma única linha.
Flexibilidade:
- Antes: Mais flexível para lógicas complexas dentro do loop.
- 21c: Mais conciso para padrões de loop comuns, mas pode ser menos flexível para lógicas muito complexas.
Risco de erro:
- Antes: Maior risco de criar loops infinitos se esquecer de incrementar a variável.
- 21c: Menor risco de loops infinitos, pois o incremento é parte integrante da definição do loop.
Compatibilidade:
- Antes: Funciona em todas as versões do Oracle.
- 21c: Funciona apenas no Oracle 21c e versões posteriores.
Em resumo, a nova sintaxe do Oracle 21c oferece uma forma mais concisa e menos propensa a erros de escrever loops com incrementos personalizados. Ela encapsula a lógica de inicialização, incremento e condição de parada em uma única estrutura, tornando o código mais legível e menos propenso a erros comuns, como esquecer de incrementar a variável de controle. No entanto, essa nova sintaxe só está disponível no Oracle 21c e versões posteriores, o que pode afetar a portabilidade do código entre diferentes versões do Oracle.
5. Múltiplas Iterações
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
DECLARE v_contador NUMBER; v_resultado VARCHAR2(100); BEGIN FOR v_contador IN 1..3, REVERSE 10..12, 100..102 LOOP CASE WHEN v_contador <= 3 THEN v_resultado := 'Primeira sequência: '; WHEN v_contador >= 10 AND v_contador <= 12 THEN v_resultado := 'Segunda sequência (reversa): '; ELSE v_resultado := 'Terceira sequência: '; END CASE; DBMS_OUTPUT.PUT_LINE(v_resultado || v_contador); END LOOP; END; / |
Vamos analisar este código:
- Declaramos
v_contador
como NUMBER ev_resultado
como VARCHAR2 para armazenar uma descrição da sequência atual. - O loop FOR usa três sequências de iteração:
1..3
: Itera de 1 a 3REVERSE 10..12
: Itera de 12 a 10 em ordem reversa100..102
: Itera de 100 a 102
- Dentro do loop, usamos um CASE para determinar em qual sequência estamos e definir a descrição apropriada.
- Finalmente, imprimimos o resultado para cada iteração.
Quando executado, este código produzirá a seguinte saída:
1 2 3 4 5 6 7 8 9 10 |
Primeira sequência: 1 Primeira sequência: 2 Primeira sequência: 3 Segunda sequência (reversa): 12 Segunda sequência (reversa): 11 Segunda sequência (reversa): 10 Terceira sequência: 100 Terceira sequência: 101 Terceira sequência: 102 |
Pontos importantes:
- As sequências são executadas na ordem em que são definidas.
- Cada sequência é completada antes de passar para a próxima.
- Você pode misturar sequências crescentes, decrescentes (usando REVERSE) e até mesmo expressões mais complexas.
- Esta funcionalidade permite criar loops mais complexos e flexíveis em uma única estrutura, o que pode levar a um código mais conciso e legível em certos cenários.
Lembre-se de que esta sintaxe só está disponível no Oracle 21c e versões posteriores. Se você estiver trabalhando com versões anteriores do Oracle, precisará usar múltiplos loops ou lógica condicional para alcançar o mesmo resultado.
Terminando o Numeric FOR Loop Prematuramente
Às vezes, precisamos sair de um loop antes que ele termine naturalmente. Podemos usar EXIT ou EXIT WHEN para isso:
Vamos explorar diferentes métodos, incluindo EXIT, EXIT WHEN, e a nova cláusula WHILE do Oracle 21c.
Usando EXIT:
O EXIT permite sair imediatamente do loop quando uma condição específica é encontrada.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
DECLARE v_contador NUMBER; BEGIN FOR v_contador IN 1..10 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); IF v_contador = 5 THEN DBMS_OUTPUT.PUT_LINE('Saindo do loop em 5'); EXIT; END IF; END LOOP; DBMS_OUTPUT.PUT_LINE('Loop terminado'); END; / |
Saída:
1 2 3 4 5 6 7 |
v_contador = 1 v_contador = 2 v_contador = 3 v_contador = 4 v_contador = 5 Saindo do loop em 5 Loop terminado |
Usando EXIT WHEN
O EXIT WHEN combina a condição e a ação de saída em uma única instrução, tornando o código mais conciso.
1 2 3 4 5 6 7 8 9 10 |
DECLARE v_contador NUMBER; BEGIN FOR v_contador IN 1..10 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); EXIT WHEN v_contador >= 7; END LOOP; DBMS_OUTPUT.PUT_LINE('Loop terminado em ' || v_contador); END; / |
Saida:
1 2 3 4 5 6 7 8 |
v_contador = 1 v_contador = 2 v_contador = 3 v_contador = 4 v_contador = 5 v_contador = 6 v_contador = 7 Loop terminado em 7 |
Usando WHILE no cabeçalho do loop (Oracle 21c)
No Oracle 21c, podemos usar a cláusula WHILE diretamente no cabeçalho do loop FOR, o que permite definir uma condição de parada juntamente com a definição do loop.
1 2 3 4 5 6 7 8 9 |
DECLARE v_contador NUMBER; BEGIN FOR v_contador IN 1..10 WHILE v_contador <= 6 LOOP DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador); END LOOP; DBMS_OUTPUT.PUT_LINE('Loop terminado após ' || (v_contador - 1)); END; / |
Saída:
1 2 3 4 5 6 7 |
v_contador = 1 v_contador = 2 v_contador = 3 v_contador = 4 v_contador = 5 v_contador = 6 Loop terminado após 6 |
Combinando WHILE com EXIT WHEN (Oracle 21c)
Podemos combinar a cláusula WHILE com EXIT WHEN para ter um controle ainda mais fino sobre a execução do loop.
1 2 3 4 5 6 7 8 9 10 11 12 |
DECLARE v_contador NUMBER; v_soma NUMBER := 0; BEGIN FOR v_contador IN 1..100 WHILE v_soma < 50 LOOP v_soma := v_soma + v_contador; DBMS_OUTPUT.PUT_LINE('v_contador = ' || v_contador || ', Soma = ' || v_soma); EXIT WHEN v_contador = 10; END LOOP; DBMS_OUTPUT.PUT_LINE('Loop terminado. Contador final: ' || v_contador || ', Soma final: ' || v_soma); END; / |
Saída:
1 2 3 4 5 6 7 8 9 10 11 |
v_contador = 1, Soma = 1 v_contador = 2, Soma = 3 v_contador = 3, Soma = 6 v_contador = 4, Soma = 10 v_contador = 5, Soma = 15 v_contador = 6, Soma = 21 v_contador = 7, Soma = 28 v_contador = 8, Soma = 36 v_contador = 9, Soma = 45 v_contador = 10, Soma = 55 Loop terminado. Contador final: 10, Soma final: 55 |
Neste último exemplo, o loop termina quando uma das duas condições é atendida: a soma atinge ou ultrapassa 50, ou o contador chega a 10. O loop termina quando o contador atinge 10, mesmo que a soma já tenha ultrapassado 50.
Importante:
- EXIT e EXIT WHEN são métodos flexíveis para sair prematuramente de loops em todas as versões do Oracle.
- A cláusula WHILE no Oracle 21c oferece uma maneira mais elegante de definir condições de parada diretamente no cabeçalho do loop.
- Você pode combinar diferentes métodos para um controle mais preciso sobre a execução do loop.
Lembre-se de que a escolha entre esses métodos depende da legibilidade do código, da complexidade da lógica e da versão do Oracle que você está usando.
Conclusão e Dicas Práticas
- Numeric FOR Loops são excelentes para iterações com um número conhecido de repetições.
- Use REVERSE quando precisar contar de trás para frente.
- Aproveite os novos recursos do Oracle 21c para loops mais flexíveis e eficientes.
- Sempre teste seus loops para garantir que eles terminem conforme esperado.
- Evite modificar o contador do loop dentro do próprio loop.
Lembre-se: a prática leva à perfeição. Experimente criar seus próprios Numeric FOR Loops, teste diferentes condições e veja como eles podem tornar seu código mais dinâmico e eficiente.