Menu

Triggers no SQLite: CREATE TRIGGER, BEFORE/AFTER e OLD/NEW

Como funcionam os triggers no SQLite: BEFORE, AFTER, INSTEAD OF em views, as referências OLD e NEW, e quando faz sentido usá-los.

Esta página tem editores executáveis — edite, execute e veja a saída na hora.

Um trigger executa SQL automaticamente

Um trigger no SQLite é um bloco de SQL armazenado que dispara sempre que um evento específico acontece em uma determinada tabela. Você escreve uma vez. O SQLite cuida do "quando" pra você.

A estrutura básica:

Em nenhum momento escrevemos um INSERT explícito em price_history — quem fez isso foi o trigger. Daqui pra frente, toda atualização de preço vai ser registrada do mesmo jeito, venha ela da CLI, de um script ou de um app.

Anatomia do CREATE TRIGGER no SQLite

Vamos destrinchar a sintaxe parte por parte:

CREATE TRIGGER trigger_name
{ BEFORE | AFTER | INSTEAD OF } { INSERT | UPDATE [ OF column_list ] | DELETE }
ON table_name
[ FOR EACH ROW ]
[ WHEN condition ]
BEGIN
    -- uma ou mais instruções
END;
  • Momento de execuçãoBEFORE dispara antes da alteração, AFTER dispara depois, e INSTEAD OF substitui a operação (apenas em views).
  • Evento — qual operação dispara o trigger. UPDATE OF col1, col2 restringe o disparo a colunas específicas.
  • Tabela — a tabela que está sendo monitorada.
  • FOR EACH ROW — o SQLite só suporta triggers por linha, então isso fica implícito. Você pode escrever para deixar claro, mas não muda nada.
  • WHEN — uma condição opcional. O corpo do trigger só roda se ela for verdadeira.
  • Corpo — um ou mais comandos entre BEGIN e END. Cada um precisa terminar com ponto e vírgula.

E é toda a sintaxe. Na prática, a maioria dos triggers tem entre cinco e dez linhas.

OLD e NEW: a linha que está sendo alterada

Dentro do corpo do trigger, você tem acesso a duas pseudo-linhas que representam os dados:

  • NEW — a linha que está chegando. Disponível em triggers de INSERT e UPDATE.
  • OLD — a linha que já existia. Disponível em triggers de UPDATE e DELETE.

Um trigger de DELETE só tem OLD. Um trigger de INSERT só tem NEW. Já um trigger de UPDATE tem os dois.

A linha apagada some de accounts, mas os dados dela foram preservados em deletions antes do sumiço.

BEFORE: validar ou ajustar a linha

Os triggers BEFORE disparam antes da mudança ser gravada em disco. São ótimos para levantar um erro ou normalizar dados antes que a alteração se concretize:

O segundo INSERT é abortado antes que qualquer linha seja gravada. O RAISE(ABORT, '...') cancela a instrução atual e desfaz tudo que ela tinha feito até ali — já o RAISE(FAIL, ...), RAISE(ROLLBACK, ...) e RAISE(IGNORE) te dão um controle mais fino sobre o que acontece.

Para validação pura de dados, prefira restrições CHECK — elas são declarativas e o otimizador as enxerga. Recorra a um trigger BEFORE quando a regra precisar consultar outras tabelas ou fizer algo que um CHECK não consegue expressar.

Cláusula WHEN: triggers condicionais no SQLite

A cláusula WHEN filtra quais alterações de linha realmente disparam o corpo do trigger. Ela é avaliada linha a linha, depois que OLD e NEW já foram associados:

O primeiro pedido fica de fora. Os outros dois passam. Sem a cláusula WHEN, todo INSERT cairia em big_orders e você teria que filtrar na hora da leitura.

INSTEAD OF: tornando uma view gravável

Por padrão, views em SQLite são somente leitura. Um trigger INSTEAD OF intercepta uma escrita feita contra a view e executa o seu SQL no lugar — normalmente traduzindo isso em escritas nas tabelas que estão por trás dela:

O aplicativo conversa com a view como se fosse uma tabela comum. Por trás dos panos, o trigger se encarrega de dividir o valor em first_name e last_name.

Listar e remover triggers no SQLite

Os triggers ficam guardados em sqlite_master, junto com as tabelas e índices:

DROP TRIGGER IF EXISTS nome; é a forma segura. Quando você dropa a tabela onde a trigger vive, ela some junto automaticamente — não precisa fazer faxina antes.

Armadilhas que vale conhecer

Algumas coisas pegam todo mundo de surpresa na primeira vez:

  • Triggers disparam por linha, não por comando. Um UPDATE que afeta 1.000 linhas dispara a trigger 1.000 vezes. Se o corpo dela já é pesado, a conta explode rápido.
  • Triggers rodam dentro da transação que as envolve. Se o comando externo der rollback, as escritas da trigger também voltam atrás. Geralmente é o que você quer, mas isso significa que trigger não é uma saída de emergência para "registrar isso aconteça o que acontecer".
  • Triggers recursivas vêm desligadas por padrão. Uma trigger que altera a mesma tabela não vai se redisparar a menos que você ative PRAGMA recursive_triggers = ON;. Deixe desligado, a não ser que tenha um motivo bem específico.
  • A aplicação só escapa das triggers se ela pular o banco. Enquanto toda escrita passar pelo SQLite, a trigger vai rodar. ORMs que mandam SQL cru em lote também disparam triggers normalmente.
  • Não espalhe regra de negócio por várias triggers. Elas são invisíveis de quem chama o código — quem estiver debugando "por que essa linha apareceu?" vai ter que sair fazendo grep em sqlite_master. Use triggers para questões transversais (logs de auditoria, colunas derivadas, tornar views graváveis) e mantenha o resto na camada de aplicação.

Um exemplo realista de log de auditoria

Juntando os padrões — vamos rastrear toda mudança numa tabela posts:

Com uma única trigger, você mantém o updated_at sempre correto e ainda grava uma linha de auditoria, tudo em um só lugar. O código da aplicação que faz o UPDATE nem precisa saber que essas duas coisas existem.

A seguir: suporte a JSON

As triggers cuidam da automação em torno de eventos de linha. O próximo recurso avançado do SQLite tem a ver com o que você consegue guardar dentro de uma linha — JSON. O SQLite oferece um conjunto completo de funções JSON para consultar e atualizar dados estruturados sem precisar sair do SQL, e é exatamente esse o tema da próxima página.

Perguntas frequentes

O que é um trigger no SQLite?

Um trigger é um bloco de SQL que roda automaticamente quando um evento específico acontece em uma tabela — um INSERT, UPDATE ou DELETE. Você define ele uma vez com CREATE TRIGGER e o próprio SQLite cuida de disparar sempre que o evento ocorre. É assim que se mantém logs de auditoria, colunas derivadas ou regras de negócio sem depender da aplicação lembrar de fazer isso.

Qual a diferença entre triggers BEFORE, AFTER e INSTEAD OF?

O BEFORE roda antes da alteração ser aplicada — bom para validar ou ajustar os dados da linha. O AFTER roda depois que a mudança já aconteceu — útil para gravar log ou sincronizar outras tabelas. Já o INSTEAD OF só funciona em views e substitui completamente a operação que aconteceria, permitindo tornar uma view gravável.

Como referenciar a linha que está sendo alterada dentro do trigger?

Use NEW.coluna para a linha que está chegando em INSERT e UPDATE, e OLD.coluna para a linha existente em UPDATE e DELETE. Triggers de INSERT só enxergam NEW, os de DELETE só enxergam OLD, e os de UPDATE enxergam os dois. Essas referências valem apenas para a linha que está sendo processada no momento.

Como listar ou remover triggers no SQLite?

Os triggers ficam guardados em sqlite_masterSELECT name, tbl_name FROM sqlite_master WHERE type = 'trigger'; lista todos. Para remover, basta DROP TRIGGER nome_do_trigger;, ou DROP TRIGGER IF EXISTS nome_do_trigger; se você não tem certeza se ele existe. Vale lembrar que apagar a tabela também apaga os triggers dela.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR