CodeGym /Cursos /SQL SELF /Interação entre funções e procedimentos

Interação entre funções e procedimentos

SQL SELF
Nível 55 , Lição 1
Disponível

Alguns níveis atrás a gente já falou sobre procedimentos e funções no PostgreSQL. Agora chegou a hora de mergulhar mais fundo nisso.

Funções e procedimentos podem funcionar de boa sozinhos, mas na real, o sucesso do sistema geralmente depende de como eles interagem. O mais massa é que funções podem chamar outras funções, passando dados e até pegando o resultado de volta.

Funções vs Procedimentos: qual a diferença?

Bora relembrar rapidinho qual é a diferença entre funções e procedimentos no PostgreSQL:

  • Funções (FUNCTION):

    • Retornam valores.
    • Dá pra usar elas no SELECT.
    • Normalmente são usadas pra calcular ou transformar dados.
  • Procedimentos (PROCEDURE):

    • Não retornam valores direto.
    • São usadas pra fazer operações tipo inserir, atualizar ou deletar dados.
    • Você chama elas usando o comando CALL.

Passando dados entre funções

Indo pra prática, vamos começar com um exemplo básico de como passar dados entre uma função e um procedimento. Basicamente, a troca de dados entre funções rola pelos parâmetros e pelos valores retornados.

Olha só como fica chamar uma função dentro de outra função:

CREATE OR REPLACE FUNCTION get_student_name(student_id INT)
RETURNS TEXT AS $$
DECLARE
    student_name TEXT;
BEGIN
    -- Pegando o nome do estudante pelo ID dele
    SELECT name INTO student_name FROM students WHERE id = student_id;

    -- Retornando o nome
    RETURN student_name;
END;
$$ LANGUAGE plpgsql;

Dá pra chamar essa função de dentro de outra função:

CREATE OR REPLACE FUNCTION welcome_student(student_id INT)
RETURNS TEXT AS $$
DECLARE
    message TEXT;
BEGIN
    -- Pegando o nome do estudante usando outra função
    message := 'Bem-vindo, ' || get_student_name(student_id) || '!';

    -- Retornando a mensagem de boas-vindas
    RETURN message;
END;
$$ LANGUAGE plpgsql;
  1. A função get_student_name retorna o nome do estudante pelo identificador dele (student_id).
  2. Na outra função — welcome_student — esse nome é usado pra montar a mensagem de boas-vindas.

Obs: Pegar dados usando SELECT INTO salva o resultado da query numa variável do PL/pgSQL.

Exemplo de chamada de procedimentos dentro de funções

Agora bora ver como chamar um procedimento de dentro de uma função. Imagina que a gente tem um procedimento que registra a hora que o estudante entrou no sistema:

CREATE OR REPLACE PROCEDURE log_student_entry(student_id INT)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO log_entries(student_id, entry_time)
    VALUES (student_id, NOW());
END;
$$;

Agora vamos chamar esse procedimento de dentro de uma função, onde ele vai registrar a entrada e retornar uma mensagem:

CREATE OR REPLACE FUNCTION student_login(student_id INT)
RETURNS TEXT AS $$
BEGIN
    -- Chamando o procedimento pra registrar o login
    CALL log_student_entry(student_id);

    -- Retornando a mensagem
    RETURN 'Login do estudante registrado com sucesso.';
END;
$$ LANGUAGE plpgsql;

Exemplos práticos de interação

Exemplo 1: cálculo do valor total do pedido e log do pedido

Pensa que você tá mexendo num sistema de pedidos online. Pra calcular o valor total do pedido, você tem uma função:

CREATE OR REPLACE FUNCTION calculate_order_total(order_id INT)
RETURNS NUMERIC AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- Somando todos os itens do pedido
    SELECT SUM(price * quantity) INTO total
    FROM order_items
    WHERE order_id = order_id;

    RETURN total;
END;
$$ LANGUAGE plpgsql;

Pra salvar o valor total do pedido, tem um procedimento:

CREATE OR REPLACE PROCEDURE log_order_total(order_id INT, total NUMERIC)
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO order_totals(order_id, total)
    VALUES (order_id, total);
END;
$$;

Agora vamos juntar tudo:

CREATE OR REPLACE FUNCTION process_order(order_id INT)
RETURNS TEXT AS $$
DECLARE
    total NUMERIC;
BEGIN
    -- Chamando a função pra calcular o total
    total := calculate_order_total(order_id);

    -- Registrando o total usando o procedimento
    CALL log_order_total(order_id, total);

    RETURN 'Pedido processado com sucesso.';
END;
$$ LANGUAGE plpgsql;

Exemplo 2: pegando a maior nota do estudante e atualizando o perfil

Função pra pegar a maior nota:

CREATE OR REPLACE FUNCTION get_highest_rating(student_id INT)
RETURNS INT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- Pegando a maior nota do estudante
    SELECT MAX(rating) INTO max_rating
    FROM ratings
    WHERE student_id = student_id;

    RETURN max_rating;
END;
$$ LANGUAGE plpgsql;

Procedimento pra atualizar o perfil do estudante:

CREATE OR REPLACE PROCEDURE update_student_profile(student_id INT, max_rating INT)
LANGUAGE plpgsql
AS $$
BEGIN
    UPDATE students
    SET highest_rating = max_rating
    WHERE id = student_id;
END;
$$;

Função pra chamar essas operações:

CREATE OR REPLACE FUNCTION refresh_student_profile(student_id INT)
RETURNS TEXT AS $$
DECLARE
    max_rating INT;
BEGIN
    -- Pegando a maior nota
    max_rating := get_highest_rating(student_id);

    -- Atualizando o perfil do estudante
    CALL update_student_profile(student_id, max_rating);

    RETURN 'Perfil atualizado com sucesso.';
END;
$$ LANGUAGE plpgsql;

Erros comuns na interação

Um dos erros mais comuns é quando os tipos de dados não batem entre a função e o procedimento. Por exemplo, se o procedimento espera um parâmetro do tipo NUMERIC, mas você manda um INTEGER, o PostgreSQL vai reclamar de incompatibilidade de tipos. Sempre confere se os tipos estão certinhos.

Outro erro é criar chamadas cíclicas, tipo a função A chama a função B, e a B chama a A de novo. Isso vira um loop infinito e derruba o sistema.

Por que isso é importante?

Pra que serve essa interação toda? No mundo real, funções e procedimentos são tipo "blocos de construção" de sistemas grandes. Eles deixam o código mais organizado, fácil de testar, de reaproveitar e de debugar. Por exemplo:

  • Em entrevista de emprego, podem pedir pra você escrever uma função que chama um procedimento pra fazer uma operação mais complexa. Mostrar que você manja disso é um baita diferencial.
  • Quando você tá desenvolvendo apps de verdade, tipo lojas virtuais, sistemas de log ou CRM, saber organizar a lógica usando funções e procedimentos deixa o código muito mais de boa de manter.

Se quiser se aprofundar mais em como funções e procedimentos interagem, dá uma olhada na documentação oficial do PL/pgSQL.

2
Tarefa
SQL SELF, nível 55, lição 1
Bloqueado
Atualização do perfil do estudante com base na pontuação
Atualização do perfil do estudante com base na pontuação
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION