none
Trigger com tabelas delete cascade RRS feed

  • Pergunta

  • Senhores,

    Alguém poderia me responder como resolver a seguinte situação:

    Tenho uma tabela PAI e outro FiLHO, onde os registros da tabela FILHO é deletado quando o registro da tabela PAI é excluido (delete cascade na tabela PAI). Existe uma trigger (for delete) na tabela FILHO que executa algumas atualizações em outras tabelas. O problema é que ao usar o recurso INNER JOIN com a tabela PAI na trigger e se tratando de exclusão de registro, o INNER JOIN não encontra o registro na tabela PAI. O mais estranho é que, sendo o evento delete cascade executado primeiro, porquê na trigger da tabela FILHO não encontra o registro no PAI, já que teoricamente seria apagado após os filhos serem apagado. 

    quarta-feira, 14 de janeiro de 2015 18:24

Respostas

  • Ola Emerson

    Pelo que entendi, sua intenção é pegar os registros excluidos e inserir em uma outra tabela.

    acredito que a clausula output poderá te ajudar e com melhor perfomance em relação ao trigger.

    http://msdn.microsoft.com/pt-br/library/ms177564.aspx

    USE tempdb;
    GO
    CREATE TABLE dbo.table1
    (
        id INT,
        employee VARCHAR(32)
    );
    GO
    
    INSERT INTO dbo.table1 VALUES 
          (1, 'Fred')
         ,(2, 'Tom')
         ,(3, 'Sally')
         ,(4, 'Alice');
    GO
    
    DECLARE @MyTableVar TABLE
    (
        id INT,
        employee VARCHAR(32)
    );
    
    PRINT 'table1, before delete' 
    SELECT * FROM dbo.table1;
    
    DELETE FROM dbo.table1
    OUTPUT DELETED.* INTO @MyTableVar
    WHERE id = 4 OR id = 2;
    
    PRINT 'table1, after delete'
    SELECT * FROM dbo.table1;
    
    PRINT '@MyTableVar, after delete'
    SELECT * FROM @MyTableVar;
    
    DROP TABLE dbo.table1;
    


    Att.
    Marcelo Fernandes

    MCP, MCDBA, MCSA, MCTS, MCITP, MCT.
    Se útil, classifique!!!
    Me siga no twitter: @marcelodba

    quarta-feira, 14 de janeiro de 2015 21:07
    Moderador

Todas as Respostas

  • Emerson, 

         Deixe-me ver se entendi direito. Em algum momento dentro da trigger você precisa fazer um join com a tabela PAI e não consegue porque a constraint já foi disparada quando do delete do registro PAI, é isso? 

         Tente ver se você pode utilizar a tabela virtual INSERTED ou DELETED, que pode ser mais adequado no seu caso...


    Roberto Fonseca MCT / MCITP - Database Administrator 2008 MCITP - Database Developer 2008 MCITP - Business Intelligence 2008

    quarta-feira, 14 de janeiro de 2015 18:49
    Moderador
  • Emerson. 

    Veja a seguinte estrutura:

    registro PAI apagado -- trigger disparado para apagar registro FILHO (fim do alcance do trigger)

    registro FILHO apagado pelo trigger -- dispara outro trigger que não tem comunicação com o primeiro (neste momento o registro PAI já não existe mais).

    O que tu tens que fazer é juntar estes dois trigger, em um só. Ai sim, tu vai ter a informação DELETED.XXX do PAI, para usar no INNER.

    quarta-feira, 14 de janeiro de 2015 19:12
  • Exatamente. Estou usando na trigger do FILHO o DELETED. Só que o inner join com a tabela PAI não encontra o registo. Veja exemplo abaixo.

    ALTER TRIGGER [dbo].[trg_estorna_ocorrencia_estoque]
    ON [dbo].[tb_mvto_compra_item]

    FOR DELETE AS 
    BEGIN

    INSERT INTO dbo.tb_mvto_estoque 

       (emvto_data) 
        SELECT c.cmp_dt_entrada

         FROM DELETED INNER JOIN dbo.tb_mvto_compra c  ON DELETED.cmp_id = c.cmp_id  

    END

    quarta-feira, 14 de janeiro de 2015 19:21
  • Parece que mesmo sendo os FILHOS excluidos primeiro, por algum motivo o PAI não existe e não é encontrado pelo inner jon. 
    quarta-feira, 14 de janeiro de 2015 19:34
  • Corrigindo sua estrutura. 

    Os Filhos são excluidos por causa do delete conscade do Pai. Não existe trigger no PAI para limpar os Filhos compreende. Somente existe trigger nos filhos usando campos do PAI conforme exemplo anterior.

    quarta-feira, 14 de janeiro de 2015 19:40
  • Emerson, 

    Aí está!

    Quando este trigger dispara, na tabela filho, o registo do pai não existe mais. Tu tens que levar estes insert into para dentro o primeiro trigger. Isto tem que ficar junto com o que faz o delete do filho.

    quarta-feira, 14 de janeiro de 2015 19:41
  • O problema é que por estar usando o delete cascade no PAI, quando for tratar o FILHO na trigger do PAI, os FILHOS  não existiram mais.  A propósito, existe como fazer referência na trigger do FILHO na área do deleted do PAI?  Caso não exista, terei que tratar a exclusão dos FILHOS na trigger do PAI, retirando o recurso de deleted cascade da tabela PAI. Gostaria de saber se também se é comum não usar deleted cascade quando se usa trigger com deleted?
    quarta-feira, 14 de janeiro de 2015 20:03
  • Boa tarde,

    Emerson, não fiz nenhum teste, mas acho que você talvez consiga fazer essa operação com uma instead of trigger na tabela pai, pois ela é acionada antes de as linhas serem excluidas.

    Espero que ajude.


    Assinatura: http://www.imoveisemexposicao.com.br


    • Editado gapimex quarta-feira, 14 de janeiro de 2015 20:15
    quarta-feira, 14 de janeiro de 2015 20:14
  • Ola Emerson

    Pelo que entendi, sua intenção é pegar os registros excluidos e inserir em uma outra tabela.

    acredito que a clausula output poderá te ajudar e com melhor perfomance em relação ao trigger.

    http://msdn.microsoft.com/pt-br/library/ms177564.aspx

    USE tempdb;
    GO
    CREATE TABLE dbo.table1
    (
        id INT,
        employee VARCHAR(32)
    );
    GO
    
    INSERT INTO dbo.table1 VALUES 
          (1, 'Fred')
         ,(2, 'Tom')
         ,(3, 'Sally')
         ,(4, 'Alice');
    GO
    
    DECLARE @MyTableVar TABLE
    (
        id INT,
        employee VARCHAR(32)
    );
    
    PRINT 'table1, before delete' 
    SELECT * FROM dbo.table1;
    
    DELETE FROM dbo.table1
    OUTPUT DELETED.* INTO @MyTableVar
    WHERE id = 4 OR id = 2;
    
    PRINT 'table1, after delete'
    SELECT * FROM dbo.table1;
    
    PRINT '@MyTableVar, after delete'
    SELECT * FROM @MyTableVar;
    
    DROP TABLE dbo.table1;
    


    Att.
    Marcelo Fernandes

    MCP, MCDBA, MCSA, MCTS, MCITP, MCT.
    Se útil, classifique!!!
    Me siga no twitter: @marcelodba

    quarta-feira, 14 de janeiro de 2015 21:07
    Moderador
  • Bom dia,

    Obrigado a todos pelo interesse em ajudar. Certamente, com base nessas soluções farei grande proveito. Saúde a todos!

    quinta-feira, 15 de janeiro de 2015 12:57
  • Bom dia Emerson,

    Que bom que você ficou satisfeito, como você não marcou como resposta irei marcar para fechar a thread beleza?

    Abraço


    Ricardo Cortes Microsoft Contingent Staff

    Esse contedo e fornecido sem garantias de qualquer tipo, seja expressa ou implicita.

    MSDN Community Support

    sexta-feira, 16 de janeiro de 2015 13:16