Usuário com melhor resposta
Trigger em várias tabelas

Pergunta
-
Bom dia,
Tenho a seguinte questão:
O sistema que utilizo, no momento de salvar, ele faz inserção em 6 tabelas, criei uma trigger para fazer uma validação na inserção da última tabela.
O problema é que esta validação utiliza dados que foram inseridos na primeira tabela, ao realizar a comparação o sistema retorna null para variável que fará a validação, como se não tivesse sido inserido dados na primeira tabela, pois faço a verificação do id.
Gostaria de saber se consigo acessar os dados que foram inseridos na primeira tabela através da trigger que executa na inserção da última tabela, ou só consigo acessar estes dados depois da transação confirmada?
Obrigado!
Emerson Costa - MSDN
Respostas
-
Denis, boa noite.
Eu prefiro usar uma transação dentro de procedure para inserir os dados nessas tabelas, e o que você pode fazer é usar output para pegar o que foi inserido na tabela anterior
ex:
USE AdventureWorks2012; GO DECLARE @MyTableVar table( NewScrapReasonID smallint, Name varchar(50), ModifiedDate datetime); INSERT Production.ScrapReason OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate INTO @MyTableVar VALUES (N'Operator error', GETDATE()); --Display the result set of the table variable. SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar; --Display the result set of the table. SELECT ScrapReasonID, Name, ModifiedDate FROM Production.ScrapReason; GO
Caso as tabelas tenham identity que se relacionam vc pode usar o @@IDENTITY para inserir na proxima.
Lembre-se de fazer toda validação antes de iniciar o begin transaction ;-)
Abs,
Douglas
Todas as Respostas
-
Boa tarde Emerson,
O insert nessas 6 tabelas estão dentro de uma transação apenas?
Se sim, você pode fazer, na trigger, uma leitura "suja" dos dados, ou seja, ler os dados que não foram confirmados ainda nas tabelas.
Pra isso pode colocar o isolation level como Read Uncommited ou usar o hint NOLOCK no select que está fazendo dentro da trigger.
Isso faz com que você consiga ler os dados das 6 tabelas, mesmo que a transação não tenha sido confirmada.
Não sei qual é o nível de acesso dessas tabelas, mas tome cuidado ao colocar esse trigger, porque ela pode onerar sua base ao ponto de prejudicar suas transações.
Espero ter ajudado![]'s
Mariana Del Nero /* Se a resposta foi útil, não esqueça de marcá-la */
-
Denis, boa noite.
Eu prefiro usar uma transação dentro de procedure para inserir os dados nessas tabelas, e o que você pode fazer é usar output para pegar o que foi inserido na tabela anterior
ex:
USE AdventureWorks2012; GO DECLARE @MyTableVar table( NewScrapReasonID smallint, Name varchar(50), ModifiedDate datetime); INSERT Production.ScrapReason OUTPUT INSERTED.ScrapReasonID, INSERTED.Name, INSERTED.ModifiedDate INTO @MyTableVar VALUES (N'Operator error', GETDATE()); --Display the result set of the table variable. SELECT NewScrapReasonID, Name, ModifiedDate FROM @MyTableVar; --Display the result set of the table. SELECT ScrapReasonID, Name, ModifiedDate FROM Production.ScrapReason; GO
Caso as tabelas tenham identity que se relacionam vc pode usar o @@IDENTITY para inserir na proxima.
Lembre-se de fazer toda validação antes de iniciar o begin transaction ;-)
Abs,
Douglas
-
Boa tarde Mariana, tudo bem?
Sim, ocorrem na mesma transação.
Você poderia me passar um exemplo de como eu faria este select?
Hoje estou fazendo da seguinte forma:
alter trigger trg_ValidaMovimento on TITMMOV FOR INSERT,UPDATE AS declare @idMov int declare @idPrd int DECLARE @cdTpMov varchar(10) DECLARE @tpBloq int declare @cdCCustoMov varchar(10) declare @cdCCustoItem varchar(10) set @idMov = (select IDMOV FROM inserted) set @cdCCustoMov = (select CODCCUSTO from TMOV where IDMOV = @idMov) SET @idPrd = (SELECT IDPRD FROM inserted) set @cdCCustoItem = (select CODCCUSTO from inserted) SET @cdTpMov = (SELECT CODTMV FROM TMOV WHERE IDMOV = @idMov) set @tpBloq = (select TPBLOQ from ZMDBLOQTPMOV where CODTMV = @cdTpMov)
Onde TMOV é a tabela que preciso fazer a leitura suja como você disse.
Obrigado pela atenção!
Emerson Costa - MSDN
-
Emerson,
Se a ideia é ler o campo CODTMV da tabela TMOV que ainda não teve o COMMIT da transação, apenas acrescente o NOLOCK no select, da seguinte maneira
SET @cdTpMov = (SELECT CODTMV FROM TMOV WITH (NOLOCK) WHERE IDMOV = @idMov)
O NOLOCK faz com que o SQL leia todos os dados da tabela, inclusive os dados que não foram "commitados", confirmados.
Isso deve te ajudar.
Mariana Del Nero /* Se a resposta foi útil, não esqueça de marcá-la */