Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Bei Löschkaskade für selbstreferenzierende Tabelle

Angenommen, Sie behalten Ihren FOREIGN KEY Einschränkung vorhanden ist, können Sie das Problem nicht in einem FOR DELETE beheben Abzug. FOR Auslöser (auch bekannt als AFTER Auslöser) Feuer nach die Aktivität hat stattgefunden. Und ein Fremdschlüssel wird verhindern eine Zeile vor dem Löschen, wenn sie Referenzen enthält. Fremdschlüsselprüfungen finden vorher statt Löschung.

Was Sie brauchen, ist ein INSTEAD OF Abzug. Sie müssen auch bedenken, dass Ihr aktueller Auslöser nur versucht hat, mit einer "Ebene" der Referenzierung umzugehen. (Wenn also Zeile 3 auf Zeile 2 und Zeile 2 auf Zeile 1 verweist und Sie Zeile 1 löschen, hat Ihr Trigger nur versucht, Zeile 2 zu entfernen)

Also so etwas wie:

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

Wenn es andere (nicht selbstreferenzierende) Einschränkungen für kaskadierende Fremdschlüssel gibt, müssen sie alle durch Aktionen in diesem Trigger ersetzt werden. In einem solchen Fall würde ich empfehlen, eine Tabellenvariable einzuführen, die die Liste aller IDs enthält, die schließlich aus den Comments gelöscht werden Tabelle:

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