Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

In caso di eliminazione in cascata per la tabella autoreferenziale

Supponendo che tu stia conservando la tua FOREIGN KEY vincolo in atto, non puoi risolvere il problema in un FOR DELETE grilletto. FOR attivatori (noti anche come AFTER trigger) si attiva dopo l'attività si è svolta. E una chiave esterna impedirà una riga dall'essere eliminata se contiene riferimenti. I controlli della chiave esterna si verificano prima cancellazione.

Quello che ti serve è un INSTEAD OF grilletto. Devi anche tenere a mente che il tuo attuale trigger ha cercato di gestire solo un "livello" di riferimento. (Quindi, se la riga 3 fa riferimento alla riga 2 e la riga 2 fa riferimento alla riga 1 e tu elimini la riga 1, il trigger ha solo provato a rimuovere la riga 2)

Quindi, qualcosa come:

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 sono presenti altri vincoli di chiave esterna a cascata (non autoreferenziali), devono essere tutti sostituiti da azioni in questo trigger. In tal caso, consiglierei di introdurre una variabile di tabella per contenere l'elenco di tutti gli ID che verranno eventualmente eliminati dai Comments tabella:

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);