For Trigger tut nicht, was er soll

ukulele

Datenbank-Guru
Beiträge
4.409
Folgendes Szenario:

Ich habe eine Testtabelle, die eine Hierachie abbildet.
Code:
pk PRIMARY KEY
fk FOREIGN KEY
bla VARCHAR

9EC68708-E3A2-4CFB-854E-09B0DCF2449B 03D86DE3-1052-4B51-ACAB-C9C75E143928 Unterorder
03D86DE3-1052-4B51-ACAB-C9C75E143928 NULL Überordner

Außerdem gibt es eine Testsicht, die mir einen Pfad zu jedem Eintrag generiert. Der Code der Testsicht sollte hierbei eigentlich keine Rolle spielen, der Vollständigkeit halber:

Code:
with c as (
    SELECT    pk,
            '/'+cast(pk as varchar(1000)) as pathid
    FROM    testtabelle b
    WHERE    b.fk IS NULL
    UNION ALL
    SELECT    b.pk,
            cast(c.pathid+'/'+cast(b.pk as varchar(36)) as varchar(1001))
    FROM    testtabelle b join c on b.fk = c.pk )
SELECT    b.pk,
        c.pathid+'/' as pfadid
FROM    c join testtabelle b on c.pk = b.pk
ORDER BY pfadid
03D86DE3-1052-4B51-ACAB-C9C75E143928 /03D86DE3-1052-4B51-ACAB-C9C75E143928/
9EC68708-E3A2-4CFB-854E-09B0DCF2449B /03D86DE3-1052-4B51-ACAB-C9C75E143928/9EC68708-E3A2-4CFB-854E-09B0DCF2449B/

Ein Trigger soll verhindern, das der Pfad rekursiv wird. Hier der Testtrigger:
Code:
-- ================================================================

-- ================================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- ================================================================

-- ================================================================
CREATE TRIGGER    [dbo].[testtrigger]
    ON            [dbo].[testtabelle]
    FOR INSERT, UPDATE
AS

BEGIN
        SET NOCOUNT ON;

        DECLARE    @pk UNIQUEIDENTIFIER
        DECLARE    @fk UNIQUEIDENTIFIER
        DECLARE    @error VARCHAR(255)

        SELECT    @pk = pk,
                @fk = fk
        FROM    INSERTED

        -- 0: Prüfen, ob sich eine Endlosschleife ergibt
        IF        @fk = @pk
        OR    (    SELECT    pfadid
                FROM    testsicht
                WHERE    pk = @fk ) LIKE '%' + cast(@pk AS CHAR(36)) + '%'
        BEGIN
                SET        @error =    'Erstellen einer rekursive Hierachie nicht möglich.' + CHAR(10)
                                    + 'Wählen Sie eine andere Überaufgabe.' + CHAR(10) + CHAR(13)
                RAISERROR(@error,16,1)
                ROLLBACK
        END
        -- 0: Ende
END
GO

Wenn ich den Code manuell ausführe, funktioniert das:
Code:
        DECLARE    @pk UNIQUEIDENTIFIER
        DECLARE    @fk UNIQUEIDENTIFIER
        DECLARE    @error VARCHAR(255)

        SELECT    @pk = pk,
                @fk = fk
        FROM    testtabelle
        WHERE    bla = 'Überordner'

        SET        @fk = (    SELECT    pk
                        FROM    testtabelle
                        WHERE    bla = 'Unterord' )

        -- 0: Prüfen, ob sich eine Endlosschleife ergibt
        IF        @fk = @pk
        OR    (    SELECT    pfadid
                FROM    testsicht
                WHERE    pk = @fk ) LIKE '%' + cast(@pk AS CHAR(36)) + '%'
        BEGIN
                SET        @error =    'Erstellen einer rekursive Hierachie nicht möglich.' + CHAR(10)
                                    + 'Wählen Sie eine andere Überaufgabe.' + CHAR(10) + CHAR(13)
                RAISERROR(@error,16,1)
                ROLLBACK
        END
        -- 0: Ende

Ergebnis:
Meldung 50000, Ebene 16, Status 1, Zeile 22
Erstellen einer rekursive Hierachie nicht möglich.
Wählen Sie eine andere Überaufgabe.


Meldung 3903, Ebene 16, Status 1, Zeile 23
Die ROLLBACK TRANSACTION-Anforderung hat keine entsprechende BEGIN TRANSACTION-Anweisung.

Führe ich aber ein Update Statement aus (mit aktivem Trigger) reagiert dieser nur, wenn fk = pk ist, nicht aber wenn der neue fk im Pfad der Sicht steht:

Code:
update testtabelle
set fk = pk
where pk = '03D86DE3-1052-4B51-ACAB-C9C75E143928'
Ergebnis: Fehler (wie gewünscht)

Code:
update testtabelle
set fk = '9EC68708-E3A2-4CFB-854E-09B0DCF2449B'
where pk = '03D86DE3-1052-4B51-ACAB-C9C75E143928'
Ergebnis: Kein Fehler
 
Werbung:
Oben