CodeGym /Cursos /SQL SELF /Loops aninhados e recursão

Loops aninhados e recursão

SQL SELF
Nível 51 , Lição 3
Disponível

Loops aninhados são loops que rodam dentro de outros loops. Imagina uma entrevista de emprego, quando uma pergunta leva a outras perguntas mais detalhadas. A lógica dos loops aninhados é assim: o loop externo faz uma iteração, e o loop interno faz várias passadas pra cada iteração do externo.

Exemplo: tabela de multiplicação

Bora criar uma função que gera a tabela de multiplicação pros números de 1 a 5. Esse é o exemplo clássico de uso de loops aninhados:

CREATE OR REPLACE FUNCTION generate_multiplication_table()
RETURNS VOID AS $$
BEGIN
  FOR i IN 1..5 LOOP -- Loop externo
    FOR j IN 1..5 LOOP -- Loop interno
      RAISE NOTICE '% x % = %', i, j, i * j; -- Logando o resultado
    END LOOP;
  END LOOP;
END;
$$ LANGUAGE plpgsql;

-- Chamando a função:
SELECT generate_multiplication_table();

Lógica de funcionamento:

  1. O loop externo pega os valores de i de 1 a 5.
  2. Pra cada valor de i, o loop interno pega os valores de j de 1 a 5.
  3. Em cada passo, os valores de i e j são combinados pra calcular o resultado da multiplicação.
  4. A saída fica tipo uma mini-tabela:
   1 x 1 = 1
   1 x 2 = 2
   ...
   5 x 5 = 25

Prática: buscando interseções em duas tabelas

Agora bora pra um exemplo mais "vida real". Imagina que a gente tem duas tabelas:

  • students (alunos, os nomes deles),
  • courses (cursos nos quais eles estão matriculados).

A gente quer achar os alunos que estão em mais de um curso. Vamos usar loops aninhados:

CREATE OR REPLACE FUNCTION find_students_with_multiple_courses()
RETURNS TABLE(student_name TEXT, course_name TEXT) AS $$
BEGIN
  FOR student IN SELECT DISTINCT student_name FROM students LOOP
    FOR course IN SELECT DISTINCT course_name FROM courses WHERE student_id = student.student_id LOOP
      RETURN QUERY SELECT student.student_name, course.course_name;
    END LOOP;
  END LOOP;
END;
$$ LANGUAGE plpgsql;

-- Chamando a função:
SELECT * FROM find_students_with_multiple_courses();

Recursão

Recursão é quando uma função chama ela mesma. É tipo pedir pra um amigo te explicar SQL e ele manda você ler a documentação, que manda você voltar pra essa mesma aula... Não confunde recursão com loop infinito. Recursão sempre tem uma "condição de parada" (o ponto onde a função para de se chamar).

Exemplo: calculando o fatorial de um número

O fatorial de um número n é o produto de todos os números de 1 até n. Por exemplo, o fatorial de 5 (escrito 5!) é 5 * 4 * 3 * 2 * 1 = 120. Olha como dá pra fazer isso com recursão:

CREATE OR REPLACE FUNCTION calculate_factorial(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
  -- Condição de parada: fatorial de 0 ou 1 é 1
  IF n = 0 OR n = 1 THEN
    RETURN 1;
  END IF;

  -- Chamada recursiva da função
  RETURN n * calculate_factorial(n - 1);
END;
$$ LANGUAGE plpgsql;

-- Chamando a função:
SELECT calculate_factorial(5); -- Resultado: 120

Lógica de funcionamento:

  1. Se n for 0 ou 1, retorna 1.
  2. Se n > 1, a função chama ela mesma com o argumento n - 1 e multiplica esse valor por n.
  3. Assim, as chamadas vão "acumulando" e depois desenrolam tudo de uma vez.

Exemplo prático: números de Fibonacci

Os números de Fibonacci são uma sequência onde cada número é a soma dos dois anteriores. A sequência começa assim: 0, 1, 1, 2, 3, 5, 8....

Bora criar uma função pra calcular o n-ésimo número da sequência:

CREATE OR REPLACE FUNCTION fibonacci(n INTEGER)
RETURNS INTEGER AS $$
BEGIN
  -- Condição de parada: os dois primeiros números já são conhecidos
  IF n = 0 THEN
    RETURN 0;
  ELSIF n = 1 THEN
    RETURN 1;
  END IF;

  -- Chamada recursiva da função
  RETURN fibonacci(n - 1) + fibonacci(n - 2);
END;
$$ LANGUAGE plpgsql;

-- Chamando a função:
SELECT fibonacci(6); -- Resultado: 8

Quando usar loops aninhados e recursão?

  1. Loops aninhados são ótimos pra trabalhar com tabelas:

    • Comparar valores entre duas tabelas.
    • Montar combinações de dados mais complexas.
  2. Recursão é melhor pra:

    • Calcular sequências (tipo fatorial, Fibonacci).
    • Trabalhar com estruturas hierárquicas (tipo árvore de categorias de produtos).

Erros comuns

Loops aninhados às vezes são "caros" em performance, principalmente com tabelas grandes. Usa só quando não dá pra resolver com SQL normal.

Quando usar recursão, garante que você tem uma "condição de parada" clara. Sem isso, vai rolar chamada infinita da função e provavelmente erro de stack overflow.

Estruturas aninhadas muito complexas podem dificultar o debug. Se ajuda usando RAISE NOTICE pra mostrar resultados intermediários.

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION