Acionadores do PostgreSQL BEFORE
Os gatilhos no PostgreSQL são funções que são executadas automaticamente em resposta a eventos específicos em uma tabela, como INSERT, UPDATE ou DELETE. Um acionador `BEFORE` é disparado antes que o evento ocorra, permitindo que você modifique os dados ou imponha restrições antes que as alterações de dados sejam confirmadas.
Uso
Os acionadores `BEFORE` são usados para validar ou modificar dados antes de serem inseridos, atualizados ou excluídos em uma tabela. Eles são frequentemente empregados para aplicar regras comerciais, validar a integridade dos dados ou atualizar automaticamente os campos.
sql
CREATE TRIGGER trigger_name
BEFORE INSERT OR UPDATE OR DELETE
ON table_name
FOR EACH ROW
EXECUTE FUNCTION function_name();
Nessa sintaxe, a palavra-chave `BEFORE` especifica que o acionador deve ser ativado antes da ocorrência do(s) evento(s) especificado(s). Os acionadores `BEFORE` diferem dos acionadores `AFTER`, pois os acionadores `BEFORE` são executados antes do evento, permitindo a manipulação de dados antes que a transação seja finalizada.
Exemplos
1. Acionador básico BEFORE INSERT
sql
CREATE OR REPLACE FUNCTION check_positive_salary()
RETURNS TRIGGER AS $$
BEGIN
IF NEW.salary < 0 THEN
RAISE EXCEPTION 'Salary cannot be negative';
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER check_salary_trigger
BEFORE INSERT
ON employees
FOR EACH ROW
EXECUTE FUNCTION check_positive_salary();
Este exemplo cria um acionador que verifica se o `salário` é positivo antes que uma nova linha seja inserida na tabela `funcionários`.
2. Acionamento do BEFORE UPDATE para registrar alterações
sql
CREATE OR REPLACE FUNCTION log_update()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO employees_audit(employee_id, old_salary, new_salary, changed_on)
VALUES(OLD.id, OLD.salary, NEW.salary, CURRENT_TIMESTAMP);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER log_update_trigger
BEFORE UPDATE
ON employees
FOR EACH ROW
EXECUTE FUNCTION log_update();
Aqui, um gatilho registra as alterações no campo `salary` em uma tabela `employees_audit` antes que ocorra uma atualização.
3. Acionador BEFORE DELETE para ações em cascata
sql
CREATE OR REPLACE FUNCTION prevent_deletion()
RETURNS TRIGGER AS $$
BEGIN
IF EXISTS (SELECT 1 FROM orders WHERE orders.employee_id = OLD.id) THEN
RAISE EXCEPTION 'Employee cannot be deleted, related orders exist';
END IF;
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER prevent_deletion_trigger
BEFORE DELETE
ON employees
FOR EACH ROW
EXECUTE FUNCTION prevent_deletion();
Esse acionador impede que você exclua um funcionário se houver ordens relacionadas na tabela `orders`.
Dicas e práticas recomendadas
- Use nomes de acionadores descritivos. Isso melhora a legibilidade e a manutenção, deixando claro o que cada acionador foi projetado para fazer.
- Mantenha as funções de acionamento simples. A lógica complexa pode levar a problemas de desempenho e é mais difícil de depurar.
- Faça um teste completo. Certifique-se de que os acionadores se comportem conforme o esperado em todos os cenários para evitar problemas de integridade de dados.
- Acionadores de documentos. Documente claramente a finalidade e a lógica de cada acionador para referência futura e colaboração da equipe.
- Considere o impacto no desempenho. Os acionadores podem afetar o desempenho; use-os criteriosamente, especialmente em tabelas grandes ou operações frequentes.
- Entenda o comportamento da transação. Os acionadores `BEFORE` são executados dentro da transação que os acionou, e as alterações podem ser revertidas se a transação falhar.
- Retorna a linha correta. Sempre retorne `NEW` ou `OLD` adequadamente para garantir que o acionador funcione corretamente.
- Desativar temporariamente os acionadores. Você pode desativar os acionadores durante operações em massa ou tarefas de manutenção usando `ALTER TABLE nome_da_tabela DISABLE TRIGGER nome_do_acionador;` e reativá-los com `ALTER TABLE nome_da_tabela ENABLE TRIGGER nome_do_acionador;`.