Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Em cascata de exclusão para tabela de auto-referência


Supondo que você esteja mantendo sua FOREIGN KEY restrição em vigor, você não pode corrigir o problema em um FOR DELETE acionar. FOR gatilhos (também conhecidos como AFTER gatilhos) disparar depois a atividade ocorreu. E uma chave estrangeira impedirá uma linha seja excluída se tiver referências. As verificações de chave estrangeira ocorrem antes eliminação.

O que você precisa é de um INSTEAD OF acionar. Você também precisa ter em mente que seu gatilho atual apenas tentou lidar com um "nível" de referência. (Então, se a linha 3 referenciar a linha 2 e a linha 2 referenciar a linha 1 e você excluir a linha 1, seu gatilho apenas tentou remover a linha 2)

Então, algo como:
CREATE TRIGGER [dbo].[T_comment_Trigger]
    ON [dbo].[Comments]
    INSTEAD OF DELETE
AS
    ;WITH IDs as (
       select id from deleted
       union all
       select c.id
       from Comments c
              inner join
            IDs i
              on
                 c.ParentID = i.id
    )
    DELETE FROM Comments
    WHERE id in (select id from IDs);

Se houver outras restrições de chave estrangeira em cascata (não autorreferenciadas), todas elas devem ser substituídas por ações neste gatilho. Nesse caso, eu recomendaria introduzir uma variável de tabela para manter a lista de todos os IDs que eventualmente serão excluídos dos Comments tabela:
CREATE TRIGGER [dbo].[T_comment_Trigger]
    ON [dbo].[Comments]
    INSTEAD OF DELETE
AS
    declare @deletions table (ID varchar(7) not null);
    ;WITH IDs as (
       select id from deleted
       union all
       select c.id
       from Comments c
              inner join
            IDs i
              on
                 c.ParentID = i.id
    )
    insert into @deletions(ID)
    select ID from IDs

    DELETE FROM OtherTable
    WHERE CommentID in (select ID from @deletions)

    --This delete comes last
    DELETE FROM Comments
    WHERE id in (select ID from @deletions);