Noções Básicas de Triggers
9 exemplos para você começar com triggers PostgreSQL - 6 básicos e 3 intermediários.
Pré-requisitos
Tabela com INSERT/UPDATE que você pode modificar em desenvolvimento.
# Desenvolvimento local com Docker (PostgreSQL 18)
docker run -d --name pg18 -e POSTGRES_PASSWORD=dev -p 5432:5432 postgres:18
psql postgres://postgres:dev@localhost:5432/postgresExemplos Básicos
1. Trigger de Linha AFTER INSERT
Executa por linha inserida.
CREATE OR REPLACE FUNCTION app.log_insert() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE NOTICE 'inserted %', NEW.id;
RETURN NEW;
END;
$$;
CREATE TRIGGER tr_log_insert AFTER INSERT ON app.accounts
FOR EACH ROW EXECUTE FUNCTION app.log_insert();- RETURN NEW em triggers de linha
- Triggers AFTER não podem modificar a linha
- Use NOTICE apenas em desenvolvimento
2. Trigger de Linha BEFORE UPDATE
Pode modificar NEW antes da escrita.
CREATE OR REPLACE FUNCTION app.touch_updated() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN
NEW.updated_at := now();
RETURN NEW;
END;
$$;- BEFORE UPDATE define colunas NEW
- Comum para
updated_at - Prefira GENERATED ou camada de app se for simples
3. Trigger em Nível de Instrução
Dispara uma vez por instrução SQL.
CREATE TRIGGER tr_stmt AFTER UPDATE ON app.accounts
FOR EACH STATEMENT EXECUTE FUNCTION app.log_insert();- Sem variáveis de linha NEW/OLD
- Use tabelas de transição para auditoria em massa
- Mais barato por linha em UPDATEs massivos
4. DROP Trigger
Remova quando a lógica for movida para o app.
DROP TRIGGER IF EXISTS tr_log_insert ON app.accounts;- Migrações devem fazer DROP antes de CREATE
- Triggers órfãos confundem a depuração
- Documente a propriedade
5. Timing do Trigger
Escolha entre BEFORE e AFTER.
-- BEFORE: validar/modificar NEW
-- AFTER: auditar/efeitos colaterais referenciando a linha final- BEFORE para validação e padrões
- AFTER para auditoria e fan-out
- INSTEAD OF apenas em views
6. Cláusula WHEN
Execução condicional do trigger.
CREATE TRIGGER tr_status AFTER UPDATE OF status ON app.orders
FOR EACH ROW WHEN (OLD.status IS DISTINCT FROM NEW.status)
EXECUTE FUNCTION app.log_insert();- Reduz ruído em UPDATEs amplos
- Não pode referenciar outras tabelas
- Teste com atualizações em massa
Exemplos Intermediários
7. Ordem de Múltiplos Triggers
Ordem alfabética de nomes por padrão.
CREATE TRIGGER a_first BEFORE INSERT ON app.accounts FOR EACH ROW EXECUTE FUNCTION app.touch_updated();
CREATE TRIGGER b_second BEFORE INSERT ON app.accounts FOR EACH ROW EXECUTE FUNCTION app.log_insert();- Nomeie triggers para a ordem desejada
- Evite conflitos de modificadores BEFORE
- Consolide triggers minúsculos quando possível
8. Trigger de Restrição
Verificação de restrição adiada.
-- CONSTRAINT TRIGGER ... DEFERRABLE INITIALLY DEFERRED- Raro; FK e CHECK geralmente são suficientes
- Executa no final do commit
- Mais difícil de depurar
9. Desabilitar Trigger na Sessão
session_replication_role ou ALTER TABLE DISABLE.
ALTER TABLE app.accounts DISABLE TRIGGER tr_log_insert;
-- carga em massa
ALTER TABLE app.accounts ENABLE TRIGGER tr_log_insert;- Requer superusuário ou proprietário
- Documente janelas de manutenção
- Reabilite antes de retornar ao tráfego do app
Versões da Stack: Esta página foi escrita para PostgreSQL 18.4 (estável 18, manutenção 17), pgvector 0.8+, PgBouncer 1.x, Patroni 3.x, e PostGIS 3.5+.