[SQL Server] TRIGGER de atualização aninhado
Por: Guilherme W.
11 de Novembro de 2015

[SQL Server] TRIGGER de atualização aninhado

Informática Geral

Ola galera. Este é meu primeiro artigo para começo de conversa. De químico e programador louco só eu tenho um pouco!

Esta noite andei fuçando no software que estou desenvolvendo, um pequeno sistema para resultados de análises químicas e me deparei com a seguinte situação: Eu precisava facilitar a atualização e inclusão de registros em tabelas de forma mais simples. Para isso imaginei a seguinte solução de escrever na tabela A colocaria infromacoes na Tabela B e C. Se atualziasse a tabela B colocaria as informações na tabela C. Pensando nisto eu resolvi brincar um pouco com TRIGGER de Inclusão, mais especificamente´após inclusão (AFTER INSERT).

Veja mais em TRIGGER de atualização aninhado no meu blog da Wordpress.

A ideia era facilitar, escreendo apenas o código da trigger da A para inserir em B. Escrever apenas o código da trigger B para inserir em C. Assim evitaria o oturo cenário que seria fazer todo o código em A para escrever na tabela B e C e isto ficaria mais complexo. Alem de referenciar as taelas B e C para a sua escrita, teriamos que ter todo cuidado para evitar de disparar a trigger da tabela B que também iria escrever na tabela C. Nesste momento devemos desativar a trigger da tabela B para evitar a escrita na tabela C o que no final das contar estariamos escrevendo duas vezes na tabela C se não tomaormos este cuidado. Desta maneira o código fica um pouco mais complexo.

Espero que tenham entendido estas logica. Vamos a prática então assim ficará mais claro a idéia.

Primeiro vamos criar duas tabelas chamada _A, _B e _C

 

CREATE TABLE [dbo].[_A](
[Indice] [int] NOT NULL,
[AA] [int] NULL
)ON [PRIMARY]

 

CREATE TABLE [dbo].[_B](
[Indice] [int] NOT NULL,
[IndiceA] [int] NOT NULL,
[BB] [varchar](50) NULL
)ON [PRIMARY]

 

CREATE TABLE [dbo].[_C](
[CC] [varchar](50) NULL
)

 

Agora vamos construir as triggers de cada uma das tabelas, menos da tabela _C

 

CREATE TRIGGER [dbo].[TRG_A_AFTER_INSERT]
ON [dbo].[_A]
AFTER INSERT
AS
BEGIN
BEGIN TRY
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @value_Indice INT;
DECLARE Inserted_Cursor CURSOR LOCAL SCROLL DYNAMIC OPTIMISTIC FOR
SELECT
inserted.Indice
FROM
inserted
OPEN Inserted_Cursor;
FETCH FIRST FROM inserted_Cursor
INTO @value_Indice;
WHILE (@@fetch_status= 0)
BEGIN
-- Adicionar estrutura em _B
INSERT INTO _B(Indice, IndiceA, BB)
VALUES(
ROUND(RAND((DATEPART(mm,GETDATE())* 100000 )
+(DATEPART(ss,GETDATE())* 1000 )
+DATEPART(ms,GETDATE()))*100000000, 0),
@value_Indice,
'');
FETCH NEXT FROM Inserted_Cursor
INTO @value_Indice;
END;
CLOSE Inserted_Cursor;
DEALLOCATE Inserted_Cursor;
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage =ERROR_MESSAGE();
SELECT @ErrorSeverity =ERROR_SEVERITY();
SELECT @ErrorState =ERROR_STATE();
RAISERROR ( @ErrorMessage,-- Message text.
@ErrorSeverity,-- Severity.
@ErrorState -- State.
);
PRINT'ERROR_MESSAGE: '+ @ErrorMessage +
' ERROR_SEVERITY: '+CAST(@ErrorSeverity AS VARCHAR(12))+
' ERROR_STATE: '+CAST(@ErrorState AS VARCHAR(12));
RETURN;
END CATCH
END;

 

CREATE TRIGGER [dbo].[TRG_B_AFTER_INSERT]
ON [dbo].[_B]
AFTER INSERT
AS
BEGIN
BEGIN TRY
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @value FLOAT; 
--Adicionar registros na tabela _C
 INSERT INTO _C(CC) VALUES(CAST(ROUND(RAND((DATEPART(mm,GETDATE())* 100000 )
+(DATEPART(ss,GETDATE())* 1000 )
+DATEPART(ms,GETDATE()))*100000000, 0) AS VARCHAR(50)));
 
--Serve para provocar o erro DIV#0
SET @value = 1;
SET @value = @value / 0;
 
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage =ERROR_MESSAGE();
SELECT @ErrorSeverity =ERROR_SEVERITY();
SELECT @ErrorState =ERROR_STATE();
RAISERROR ( @ErrorMessage,-- Message text.
@ErrorSeverity,-- Severity.
@ErrorState -- State.
);
PRINT'ERROR_MESSAGE: '+ @ErrorMessage +
' ERROR_SEVERITY: '+CAST(@ErrorSeverity ASVARCHAR(12))+
' ERROR_STATE: '+CAST(@ErrorState ASVARCHAR(12));
RETURN;
END CATCH
END;
 
Pronto já Possuimos as 3 estruturas de tabela com seus trigger.
 
Perceba que não coloquei nenhum BEGIN TRAN finalizado com COMMIT TRAN por que a propria execução da trigger no atual seção do sql server internamente dispara a transação e somente após todas as trigger ou rpocessos terminarem de executar dentro da seção é que ocorre um COMMIT TRAN a não ser que ocorra erro antes disso em que é executado um ROLLBACK TRAN. Neste caso todas as ações de escrever, delatar e atualizar serão desfeitas como que nada tivesse acontecido. Eu então coloquei no código acima exatamente este ponto que quero mostrar como as inclusões de registros da tabela _A e _B são desfeita quando ocorre divisão por zero.
 
SET @value = 1;
SET @value = @value / 0;
 
Removendo a linha acima, perceberá que as 3 tabelas serão atualizadas de forma aninhada (NESTED).
 
Abaixo eu coloco uma T-SQL de teste para inclusão de registros na tabela _A
 
INSERT INTO _A(Indice, AA)VALUES (1, 100);
INSERT INTO _A(Indice, AA)VALUES (2, 100);
INSERT INTO _A(Indice, AA)VALUES (3, 100);
INSERT INTO _A(Indice, AA)VALUES (4, 100);
 

É isto por enquanto pessoal e espero ter ajudado a quem estava com dúvidas se realmente ao escrever na tabela A (disparando o seu trigger) iria atualizar a tabela B (disparando seu trigger) iria por sua vez escrever na tabela C.

 

 

 

R$ 40 / h
Guilherme W.
São Paulo / SP
Guilherme W.
Identidade verificada
  • CPF verificado
  • E-mail verificado
1ª hora grátis
Informática Geral - Assembly x86 Informática Geral - Programação Delphi
Doutorado: Química (em andamento) (Universidade de São Paulo (USP))
Aulas de química orgânica, inorgânica, programação assembly x86 e delphi
Cadastre-se ou faça o login para comentar nessa publicação.

Confira artigos similares

Confira mais artigos sobre educação

+ ver todos os artigos

Encontre um professor particular

Busque, encontre e converse gratuitamente com professores particulares de todo o Brasil