CodeGym /Cursos /SQL SELF /Controle de execução de funções: PERFORM

Controle de execução de funções: PERFORM

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

PERFORM no mundo do PostgreSQL é tipo aquele herói silencioso e casca-grossa: chega, faz o que precisa e some, sem deixar rastros de dados retornados. Esse comando é usado quando você quer rodar uma query SQL dentro de uma função PL/pgSQL, mas não precisa tratar ou guardar o resultado. O objetivo principal do PERFORM é disparar uma query pra que algo aconteça, tipo modificar dados ou chamar outra função, e não pra pegar algum retorno.

PERFORM é usado quando o resultado da query não interessa pra gente. Diferente do SELECT normal, que espera que você faça algo com o resultado, o PERFORM só executa a query e segue o baile. Isso é muito útil quando você chama uma função só pelo efeito colateral dela, tipo gravar algo no log. Assim o código fica mais limpo e direto ao ponto: menos firula, mais sentido.

Exemplos de uso do PERFORM

Chamando funções

Bora ver um exemplo real. Imagina que a gente tem uma função log_action que grava informações das ações do usuário nos logs. Essa função não retorna nada, e a gente só quer que ela rode. Olha como faz com o PERFORM:

CREATE OR REPLACE FUNCTION log_action(user_id INT, action TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO logs (user_id, action, log_time)
    VALUES (user_id, action, NOW());
END;
$$ LANGUAGE plpgsql;

-- Agora a gente usa o PERFORM pra chamar essa função:
PERFORM log_action(5, 'Usuário fez login');

O que tá rolando aqui? O comando PERFORM chama a função log_action, que insere um registro na tabela logs. Fica ligado: o resultado da função é ignorado. A gente usa ela só pelo efeito, não pelo valor de retorno.

Atualizando dados

Às vezes o PERFORM é útil quando você precisa rodar uma query pra mudar dados e não liga pro resultado. Por exemplo, vamos atualizar o status de um pedido na tabela orders.

CREATE OR REPLACE FUNCTION update_order_status(order_id INT, new_status TEXT) RETURNS VOID AS $$
BEGIN
    UPDATE orders
    SET status = new_status
    WHERE id = order_id;
END;
$$ LANGUAGE plpgsql;

-- Usando o PERFORM pra chamar essa função:
PERFORM update_order_status(101, 'Enviado');

Aqui o update_order_status muda o status do pedido com id 101. Não estamos nem aí pro resultado da query dentro da função, então PERFORM é perfeito.

Rodando operações auxiliares

Às vezes as funções têm mini-operações, tipo uma lógica "auxiliar" que ajuda a fechar um processo mais complexo. Suponha que a gente queira limpar o cache depois de atualizar uma tabela:

CREATE OR REPLACE FUNCTION clear_cache() RETURNS VOID AS $$
BEGIN
    DELETE FROM cache_table;
END;
$$ LANGUAGE plpgsql;

-- Chamando ela dentro de outra função:
CREATE OR REPLACE FUNCTION update_product(product_id INT, new_price NUMERIC) RETURNS VOID AS $$
BEGIN
    UPDATE products
    SET price = new_price
    WHERE id = product_id;

    -- Limpando o cache depois de mudar os dados:
    PERFORM clear_cache();
END;
$$ LANGUAGE plpgsql;

Olha a mágica: você pode executar várias ações em sequência, usando PERFORM pra chamar funções cujo resultado não interessa nem um pouco.

Exercícios práticos

Bora ver uns exemplos de como o PERFORM pode facilitar a vida do dev.

Exemplo 1: logando etapas de uma procedure

Imagina que a gente tem um procedimento de processamento de pagamento, e precisa rastrear cada etapa, gravando tudo no log. Podemos criar uma função log_stage pra registrar as infos, e depois usar o PERFORM:

CREATE OR REPLACE FUNCTION log_stage(stage_name TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO process_logs(stage, log_time)
    VALUES (stage_name, NOW());
END;
$$ LANGUAGE plpgsql;

-- Exemplo de procedure:
CREATE OR REPLACE FUNCTION process_payment(payment_id INT) RETURNS VOID AS $$
BEGIN
    -- Logando o início
    PERFORM log_stage('Início do processamento do pagamento');

    -- Primeira etapa
    UPDATE payments
    SET status = 'Processando'
    WHERE id = payment_id;

    PERFORM log_stage('Status do pagamento atualizado');

    -- Etapa final
    UPDATE payments
    SET status = 'Concluído'
    WHERE id = payment_id;

    PERFORM log_stage('Pagamento concluído');
END;
$$ LANGUAGE plpgsql;

Aqui o log_stage é chamado via PERFORM pra registrar o estado em cada etapa do processo. Isso deixa o código bem mais fácil de debugar.

Exemplo 2: disparando notificações

Pensa numa sistema de notificações, onde você precisa mandar um aviso depois de cada ação importante. O PERFORM pode ser usado pra chamar a função responsável por isso:

CREATE OR REPLACE FUNCTION send_notification(user_id INT, message TEXT) RETURNS VOID AS $$
BEGIN
    INSERT INTO notifications (user_id, message, created_at)
    VALUES (user_id, message, NOW());
END;
$$ LANGUAGE plpgsql;

-- Usando na procedure:
CREATE OR REPLACE FUNCTION complete_task(task_id INT) RETURNS VOID AS $$
DECLARE
    user_id INT;
BEGIN
    -- Pegando o responsável pela tarefa
    SELECT assigned_to INTO user_id
    FROM tasks
    WHERE id = task_id;

    -- Finalizando a tarefa
    UPDATE tasks
    SET status = 'Concluída'
    WHERE id = task_id;

    -- Mandando notificação
    PERFORM send_notification(user_id, 'Sua tarefa foi concluída');
END;
$$ LANGUAGE plpgsql;

Aqui o PERFORM deixa claro que o que importa é só o efeito colateral — mandar a notificação, sem ligar pro retorno da função.

Dicas úteis e erros comuns

Quando você usa o PERFORM, tem que ficar ligado em alguns detalhes. Por exemplo, PERFORM não verifica se a query retornou dados. Ou seja, se o resultado da função ou da query for importante pra lógica, é melhor usar SELECT INTO. Olha só:

-- Erro comum
PERFORM alguma_funcao_que_precisa_retornar_valor();

-- Correto
SELECT alguma_funcao_que_precisa_retornar_valor() INTO alguma_variavel;

Outro erro frequente é usar PERFORM quando você realmente precisa do resultado da query, tipo numa validação de dados. Nesses casos, claro, tem que pegar o resultado e checar.

No mundo real, o comando PERFORM ajuda a deixar funções e procedures mais simples, fáceis de ler e debugar. Junto com logging (RAISE NOTICE) e funções de diagnóstico do PostgreSQL, tipo current_query(), ele vira uma ferramenta chave pra criar sistemas confiáveis, controláveis e fáceis de entender.

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