none
Trigger em várias tabelas RRS feed

  • 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

    segunda-feira, 27 de maio de 2013 15:04

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

    segunda-feira, 27 de maio de 2013 21:36

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 */

    segunda-feira, 27 de maio de 2013 20:28
  • 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

    segunda-feira, 27 de maio de 2013 21:36
  • 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

    terça-feira, 28 de maio de 2013 19:08
  • 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 */

    terça-feira, 28 de maio de 2013 20:51