O que são Triggers no MySQL?
Um trigger (ou gatilho) no MySQL é um bloco de código procedural armazenado no banco de dados que é executado automaticamente em resposta a eventos específicos em uma tabela. Semelhante a uma stored procedure, sua principle função é garantir a integridade dos dados. Eles são extremamente úteis para manter a consistência entre tabelas relacionadas, realizar auditorias de alterações (logs) e validar regras de negócio complexas antes que os dados sejam persistidos.
Vantagens e Desvantagens
Benefícios
- Automação: São executados de forma transparente e imediata sempre que ocorre uma modificação na tabela associada.
- Validação Avançada: Permitem a implementação de regras de integridade muito mais sofisticadas do que as oferecidas por constraints padrão como
FOREIGN KEYouCHECK. - Consistência: Facilitam a atualização em cascata e garantem que dados dependentes em múltiplas tabelas permaneçam sincronizados.
Limitações
- Complexidade de Manutenção: A lógica de negócios embutida em triggres pode se tornar invisível para a aplicação, dificultando o rastreamento de bugs e o debugging, especialmente em arquiteturas com muitos gatilhos.
- Acoplamento: O uso excessivo pode espalhar regras de negócio pelo banco de dados, tornando a estrutura do código difícil de compreender e gerenciar.
- Impacto no Desempenho: Em operações de alto volume (bulk inserts/updates), a execução síncrona dos triggers pode introduzir uma sobrecarga significativa no servidor de banco de dados.
Classificação e Comportamento
O MySQL suporta triggers acionados por três operações DML (Data Manipulation Language): INSERT, UPDATE e DELETE. Além disso, eles podem ser configurados para disparar BEFORE (antes) ou AFTER (depois) da operação. Atualmente, o MySQL suporta apenas triggers em nível de linha (FOR EACH ROW).
Durante a execução, o MySQL disponibiliza duas tabelas virtuais (ou pseudo-registros) para acessar os dados em transição:
- NEW: Contém os valores que estão sendo inseridos ou os novos valores de uma atualização.
- OLD: Contém os valores originais antes de uma atualização ou exclusão.
Triggers de Inserção (INSERT)
Disparados ao adicionar novos registros. O objeto NEW é utilizado para acessar os dados de entrada. Em triggers BEFORE INSERT, é possível modificar os valores de NEW para alterar o que será efetivamente salvo. Para colunas auto-incrementáveis, o valor de NEW só estará disponível no estágio AFTER.
Triggers de Atualização (UPDATE)
Acionados quando registros existentes são modificados. Ambos os objetos OLD (dados anteriores) e NEW (novos dados) estão acessíveis. Triggers BEFORE UPDATE permitem interceptar e alterar os valores em NEW. O objeto OLD é estritamente somente leitura. Vale notar que um trigger não pode modificar a própria tabela que o acionou no estágio AFTER, para evitar loops infinitos (erro de mutating table).
Triggers de Exclusão (DELETE)
Executados ao remover dados. Apenas o objeto OLD está disponível, pois não há novos dados sendo gerados. Assim como no UPDATE, os valores em OLD são somente leitura.
Tratamento de Erros
Se um trigger BEFORE falhar, a operação DML correspondente é abortada. Se um trigger AFTER falhar, toda a transação é revertida (em tabelas transacionais como InnoDB). Um trigger AFTER só é executado se o trigger BEFORE e a operação DML principal forem bem-sucedidos.
Sintaxe e Gerenciamento
Criação de Triggers
A instrução CREATE TRIGGER é utilizada para definir um novo gatilho. O nome deve ser único dentro do esquema do banco de dados.
CREATE TRIGGER nome_do_trigger
{ BEFORE | AFTER } { INSERT | UPDATE | DELETE }
ON nome_da_tabela
FOR EACH ROW
BEGIN
-- Instruções SQL
END;
Exemplo Prático: Sistema de Auditoria de Produtos
Abaixo, demonstramos como registrar as alterações de uma tabela de products em uma tabela de auditoria chamada audit_logs.
1. Registrando Novas Inserções:
DELIMITER //
CREATE TRIGGER trg_audit_product_insert
AFTER INSERT ON products
FOR EACH ROW
BEGIN
INSERT INTO audit_logs (log_action, log_timestamp, target_id, description)
VALUES (
'INSERT',
CURRENT_TIMESTAMP,
NEW.id,
CONCAT('Produto criado: ', NEW.product_name, ' | Preço: ', NEW.price)
);
END //
DELIMITER ;
2. Rastreando Atualizações:
DELIMITER //
CREATE TRIGGER trg_audit_product_update
AFTER UPDATE ON products
FOR EACH ROW
BEGIN
IF OLD.price != NEW.price THEN
INSERT INTO audit_logs (log_action, log_timestamp, target_id, description)
VALUES (
'UPDATE',
CURRENT_TIMESTAMP,
NEW.id,
CONCAT('Alteração de preço - De: ', OLD.price, ' Para: ', NEW.price)
);
END IF;
END //
DELIMITER ;
3. Log de Exclusões:
DELIMITER //
CREATE TRIGGER trg_audit_product_delete
AFTER DELETE ON products
FOR EACH ROW
BEGIN
INSERT INTO audit_logs (log_action, log_timestamp, target_id, description)
VALUES (
'DELETE',
CURRENT_TIMESTAMP,
OLD.id,
CONCAT('Produto excluído: ', OLD.product_name)
);
END //
DELIMITER ;
Consulta e Inspeção
Para listar os gatilhos existentes no banco de dados atual, utiliza-se o comando:
SHOW TRIGGERS;
Para uma inspeção mais detalhada, o dicionário de dados information_schema armazena metadados sobre todos os triggers:
SELECT * FROM information_schema.triggers WHERE trigger_name = 'trg_audit_product_insert';
Remoção de Triggers
Quando um gatilho não é mais necessário, ele pode ser eliminado do banco de dados utilizando o comando DROP TRIGGER:
DROP TRIGGER IF EXISTS trg_audit_product_insert;