Triggers
Uma trigger, ou gatilho, é um comando SQL armazenado no banco de dados que é executado automaticamente quando ocorre um evento em uma tabela. Os eventos que podem disparar uma trigger são operações de inserção, atualização ou exclusão de registros, que correspondem aos comandos INSERT
, UPDATE
e DELETE
.
Um trigger pode ser configurada para atuar antes (BEFORE) ou depois (AFTER) do evento. Esse recurso é comum para garantir regras de integridade, manter auditoria das operações e automatizar cálculos ou históricos dentro do próprio banco de dados.
Estrutura de uma Trigger
A sintaxe básica para criação de uma trigger no MySQL é a seguinte:
CREATE TRIGGER nome_trigger
{BEFORE | AFTER} {INSERT | UPDATE | DELETE}
ON nome_tabela
FOR EACH ROW
BEGIN
/* código sql*/
END;
Dentro do trigger, é possível acessar os valores novos e antigos das colunas. O identificador NEW.coluna
representa o valor novo, disponível em operações de INSERT
e UPDATE
, enquanto OLD.coluna
representa o valor antigo, utilizado em UPDATE e DELETE.
Tipos de Triggers
No MySQL é possível criar até seis tipos de triggers por tabela, uma para cada combinação de evento e momento. Essas combinações são BEFORE INSERT, AFTER INSERT, BEFORE UPDATE, AFTER UPDATE, BEFORE DELETE e AFTER DELETE. Cada uma delas tem seu uso mais apropriado, como validação de dados antes da inserção, registro de histórico de alterações ou restrição de exclusão de registros importantes.
Exemplos Práticos
Um exemplo comum é a criação de uma trigger de auditoria que registra automaticamente cada inserção de livro em uma tabela de log:
CREATE TABLE log_livros (
id INT AUTO_INCREMENT PRIMARY KEY,
titulo VARCHAR(255),
data_insercao TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
DELIMITER //
CREATE TRIGGER trg_log_livros
AFTER INSERT ON livro
FOR EACH ROW
BEGIN
INSERT INTO log_livros (titulo)
VALUES (NEW.titulo);
END;
DELIMITER ;
Outro exemplo é a criação de uma trigger de validação, que impede a inserção de um livro sem título. Nesse caso, utiliza-se a cláusula BEFORE INSERT para verificar os valores e, em caso de inconsistência, lançar um erro com o comando SIGNAL:
DELIMITER //
CREATE TRIGGER trg_valida_titulo
BEFORE INSERT ON livro
FOR EACH ROW
BEGIN
IF NEW.titulo IS NULL OR NEW.titulo = '' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Título do livro não pode ser vazio.';
END IF;
END;
DELIMITER ;
As triggers também podem ser utilizadas para manter histórico de alterações. Por exemplo, ao atualizar o preço de um livro, o valor anterior pode ser armazenado em uma tabela de histórico antes da modificação ser aplicada:
CREATE TABLE historico_preco (
id INT AUTO_INCREMENT PRIMARY KEY,
livro_id INT,
preco_antigo DECIMAL(10,2),
preco_novo DECIMAL(10,2),
data_alteracao TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
DELIMITER //
CREATE TRIGGER trg_historico_preco
BEFORE UPDATE ON livro
FOR EACH ROW
BEGIN
IF NEW.preco <> OLD.preco THEN
INSERT INTO historico_preco (livro_id, preco_antigo, preco_novo)
VALUES (OLD.id, OLD.preco, NEW.preco);
END IF;
END;
DELIMITER ;
Também é possível restringir exclusões de registros relevantes. Uma trigger configurada como BEFORE DELETE pode, por exemplo, impedir a exclusão de livros publicados antes de 1900:
DELIMITER //
CREATE TRIGGER trg_restricao_delete
BEFORE DELETE ON livro
FOR EACH ROW
BEGIN
IF OLD.ano_publicacao < 1900 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Não é permitido excluir livros históricos.';
END IF;
END;
DELIMITER ;
Trigger com Operação SELECT
Além das operações básicas, é possível criar triggers que utilizam SELECT para verificar condições mais complexas. Por exemplo, para impedir que o preço de um livro seja maior que a média dos preços de todos os livros do mesmo autor:
DELIMITER //
CREATE TRIGGER trg_limite_preco_autor
BEFORE UPDATE ON livro
FOR EACH ROW
BEGIN
DECLARE media_autor DECIMAL(10,2);
SELECT AVG(preco) INTO media_autor
FROM livro
WHERE autor = NEW.autor;
IF NEW.preco > media_autor THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'O preço não pode ser maior que a média dos livros do mesmo autor.';
END IF;
END;
//
DELIMITER ;
Nesse exemplo, o trigger faz uma consulta dentro do bloco BEGIN ... END
para obter a média dos preços (SELECT AVG(preco) INTO media_autor)
e, em seguida, compara com o novo preço. Se a condição for violada, o SIGNAL interrompe a atualização.
Considerações Finais
É importante mencionar que triggers devem ser utilizadas com cuidado. Apesar de muito úteis para automatizar processos e garantir integridade, elas podem tornar o banco de dados mais difícil de entender e manter, já que são executadas em segundo plano. Assim, recomenda-se utilizar triggers para auditoria, integridade e automações simples, mantendo regras de negócio mais complexas na camada da aplicação.