Este artigo se aplica ao Microsoft SQL Server a partir da versão 2000, porém o conceito de triggers se aplica à maioria dos sistemas gerenciadores de bancos de dados do mercado.
Olá caros sqlnautas. Neste artigo, trarei a vocês algumas dicas importantes sobre TRIGGERS no SQL Server. Este recurso nos possibilita disparar eventos programados ao se inserir, excluir ou alterar dados em uma tabela. Um exemplo de aplicação, que vamos abordar neste tópico, será a criação de uma trigger em uma tabela dos itens de uma nota fiscal. Quando os itens são gravados nesta tabela, automaticamente a trigger irá movimentar o estoque. Lembrando que nesta primeira parte, os scripts de exemplo foram desenvolvidos apenas para ilustrar. Na segunda parte, fornecerei scripts completos para realizar as simulações em seu próprio SQL Server.
CONHECENDO A ESTRUTURA DE UMA TRIGGER
Uma trigger (gatilho) é um bloco de código T-SQL (como um procedimento) que é executado no momento em que ocorre um INSERT, UPDATE e/ou DELETE na tabela onde foi criada.
Vamos então começar visualizando uma trigger. Para abrir uma trigger, podemos faze-lo de duas formas:
1. Localizar a trigger através do Object Explorer do Microsoft SQL Server Management Studio (imagem abaixo), clicar com o botão direito sobre ela e clicar em MODIFY (modificar).
2. Utilizando o comando sp_helptext
Vamos agora rapidamente olhar um código documentado de uma trigger completa (baixa estoque ao inserir itens na nota):
- CREATE trigger tgiNotaItem on NotaItem
- for insert
- as
- begin
- /*
- Autor: Fabiano Cores
- Data : 06/12/2010
- Site : http://sqlburger.blogspot.com
- Desenvolvido para demonstrar a utilização de
- triggers no SQL Server. A reprodução deste
- artigo só é permitida se forem mantidos os
- créditos do autor.
- */
- /* A tabela inserted existe "virtualmente" durante
- a execução de uma trigger. Ela possui exatamente
- a mesma estrutura da tabela da trigger, e contem
- todos os registros inseridos no evento INSERT,
- que disparou a trigger. */
- declare @vcd_empresa smallint
- declare @vnr_serie char(3)
- declare @vnr_nota int
- declare @vcd_item char(13)
- declare @vqt_faturada decimal(10,4)
- declare @vvl_unitario money
- declare cur_NF_Item cursor
- local fast_forward read_only for
- select cd_empresa
- , nr_serie
- , nr_nota
- , cd_item
- , qt_faturada
- , vl_unitario
- from inserted
- open cur_NF_Item
- while 1 = 1
- begin
- fetch next from cur_NF_Item into @vcd_empresa
- , @vnr_serie
- , @vnr_nota
- , @vcd_item
- , @vqt_faturada
- , @vvl_unitario
- if @@fetch_status <> 0 break
- /* Para cada item que foi inserido, executo o
- procedimento que movimenta estoque (só para
- exemplificar) */
- exec spcMovimentaEstoque @vcd_empresa
- , @vnr_serie
- , @vnr_nota
- , @vcd_item
- , @vqt_faturada
- , @vvl_unitario
- end
- close cur_NF_Item
- deallocate cur_NF_Item
- end
CABEÇALHO DE UMA TRIGGER
- O primeiro parâmetro é o NOME (tgiNotaItem) da trigger, forma como o objeto será identificado no banco de dados. Quando uma trigger é criada, é gerado um registro na tabela SYSOBJECTS. Para se atribuir o nome da trigger, tenho como padrão colocar tgiTabela (trigger de insert), tgdTabela (trigger de delete), tguTabela (trigger de update), ou somente tgTabela, quando ambas as situações são contempladas no código.
- O segundo parâmetro é o nome da tabela que será vinculada a esta trigger (no exemplo abaixo, estamos colocando um gatilho na tabela NotaItem).
- O terceiro parâmetro (“for insert”) determina o tipo de trigger, que vamos entender melhor cada uma adiante.
- create trigger trigger_name
- on { table_name }
- { FOR / AFTER | INSTEAD OF }
- { [INSERT] [,] [DELETE] [,] [UPDATE] }
- as
- begin
- sql_statement [ ...n ]
- end
Tipos de triggers
Existem 2 tipos de triggers no SQL Server (e na maioria dos SGBD do mercado).
AFTER: A trigger somente é executada após a gravação dos dados na tabela (padrão quando cria trigger)
INSTEAD OF: A trigger será disparada ANTES do registro ser modificado na tabela.
O tipo AFTER é o mais comum de ser utilizado. O tipo INSTEAD OF tem aplicações mais específicas. Os casos mais comuns em que utilizei este tipo de trigger foi para criar bloqueios em sistema que não detenho o código fonte (exemplo: lançamentos contábeis em período fechado, não permite gravar). Mais adiante falaremos mais sobre este tipo.
Exemplos:
AFTER
- CREATE trigger tgiNotaItem on NotaItem
- FOR { insert | delete | update }
- as
- OU
- CREATE trigger tgiNotaItem on NotaItem
- AFTER { insert | delete | update }
- as
INSTEAD OF
- CREATE trigger tgiNotaItem on NotaItem
- INSTEAD OF { insert | delete | update}
- as
Eventos de disparo de uma trigger
Uma trigger é disparada quando um evento de INSERT, DELETE ou UPDATE ocorre em uma tabela. Para isso, é necessário informar ao SQL que tipo de evento deseja tratar, que pode INSERT, DELETE ou UPDATE.
Exemplos:
- -- Trigger que será executada ao inserir um item no sistema
- CREATE trigger tgiNotaItem on NotaItem
- FOR insert
- as
- sql_statement [ ...n ]
- -- Trigger que será executada ao excluir um item no sistema
- CREATE trigger tgdNotaItem on NotaItem
- FOR delete
- as
- sql_statement [ ...n ]
- -- Trigger que será executada em qualquer operação de manipulação
- -- de dados na tabela (insert, delete ou update)
- CREATE trigger tgNotaItem on NotaItem
- FOR insert, delete, update
- as
- sql_statement [ ...n ]
TABELAS “DE AMBIENTE” EXISTENTES NA EXECUÇÃO DE UMA TRIGGER
Ao desenvolver uma trigger, você precisa ter acesso aos dados EM ATUALIZAÇÃO (no caso de insert, quais dados estão sendo inseridos, para exclusão quais estão sendo excluídos, e assim por diante). Para isso, chamo-as de “tabelas de ambiente”, que só existem no momento em que uma trigger está sendo executada.
Existe duas tabelas, chamadas INSERTED (registros incluídos ou alterados – novos valores) e DELETED (registros excluídos ou alterados – valores anteriores). Estas tabelas “virtuais” possuem exatamente a mesma estrutura da tabela em que a trigger foi criada. Vamos separar somente o trecho do código que busca dados desta tabela.
Exemplo:
- CREATE trigger tgiNotaItem on NotaItem
- for insert
- as
- begin
- ...
- declare cur_NF_Item cursor
- local fast_forward read_only for
- select cd_empresa
- , nr_serie
- , nr_nota
- , cd_item
- , qt_faturada
- , vl_unitario
- from inserted
- open cur_NF_Item
- ...
- end
Observe que estou buscando dados de uma tabela INSERTED, porém se olhar esta tabela no Object Explorer, perceberá que ela não existe. Ela somente vai existir durante a execução de uma trigger. Os updates são ainda mais interessantes. Toda vez que um UPDATE é feito em uma tabela, durante a execução da trigger nós teremos na tabela DELETED quais eram os dados antes do update, e na INSERTED quais são os novos valores dos registros alterados.
Fique atento para o próximo capítulo da saga. Na próxima parte vamos entender mais sobre a parte prática, parâmetros e o comportamentos das triggers.
=)
Parabéns pelo trabalho! Pra mim que não manjava de Trigger, esta me ajudando bastante!
ResponderExcluirCara, obrigado pelo comentário! A correria anda tão grande que não estou tendo tempo pra publicar, mas valeu pelo incentivo! Espero ter ajudado!
ExcluirValew jovem... sua explicação é muito boa.. tranquila e pontual... explicação de quem sabe explicar!!!
ResponderExcluirme ajudou bastante
Este tópico ajuda bastante! Valeu mesmo por compartilhar o seu conhecimento!!!
ExcluirMuito top! Parabens continue com o trabalho foi excelente pra mim!
ResponderExcluir