T-SQL-Trigger zum Aktualisieren von Spalten

7

Ich arbeite seit einigen Wochen mit SQL-Abfragen und versuche, aus meinen Fehlern zu lernen und zu verstehen. Ich habe eine Tabelle mit zwei Spalten IsInvisible (bit)und ShortName (string)und wenn eine geändert wird, um die andere zu aktualisieren, mag ich auch: - wenn ein ~ vor dem Kurznamen hinzugefügt wird, um IsInvisibleauf 1 zu setzen , und wenn ~ entfernt wird, um es auf 0 zu setzen - wenn IsInvisiblegesetzt ist 1, um ~ vor dem Kurznamen hinzuzufügen, und wenn auf 0 gesetzt, um ihn zu entfernen.

Ich habe so etwas versucht wie:

ALTER TRIGGER [dbo].[updateInvisibility]
ON [dbo].[table]
AFTER UPDATE
AS
BEGIN

UPDATE t
SET IsInvisible = (CASE WHEN i.ShortName like '~%' THEN 1 ELSE 0 END),
    ShortName = (CASE WHEN i.IsInvisible = 1 AND t.ShortName NOT LIKE '~%'
                 THEN '~' + t.ShortName
                 ELSE t.ShortName
            END)
FROM table t JOIN
     inserted i
     ON t.Id = i.Id;

end

Mein Problem ist, dass beim Aktualisieren einer oder beider Spalten nichts passiert und folgende Fehlermeldung angezeigt wird:

Maximum stored procedure, function, trigger, or view nesting level exceeded (limit 32)

Was mache ich falsch?

Die Option "Auslöser zulassen, andere auszulösen" zeigt "True" an.

Dana
quelle
Haben Sie weitere Auslöser in dieser Tabelle?
Shaulinator

Antworten:

10

Hier ist das Problem:

  1. Sie aktualisieren die Tabelle
  2. Es löst den Update-Trigger aus: updateInvisibility
  3. Im Trigger aktualisieren Sie die Tabelle erneut, damit der Trigger updateInvisibilityausgelöst wird

und dann macht es das so, dass Sie den Trigger am Ende viele Male auf eine Art rekursive Weise auslösen, ohne es zu merken. SQL Server lässt zu, dass diese Anrufverschachtelung 32 Ebenen tief ist, und löst dann den folgenden Fehler aus:

Maximal gespeicherte Prozedur, Funktion, Trigger oder Ansichtsverschachtelung überschritten (Limit 32)

das ist ziemlich klar.

T-SQL-Lösung

Die Nur-Code-Lösung besteht darin, die Verschachtelungsebene zu überprüfen und zu verlassen, wenn sie größer als 1 ist (1 wird beim Update zum ersten Mal aufgerufen):

IF TRIGGER_NESTLEVEL() > 1 RETURN;

So was:

ALTER TRIGGER [dbo].[updateInvisibility]
ON [dbo].[table]
AFTER UPDATE
AS
BEGIN
    IF TRIGGER_NESTLEVEL() > 1 RETURN;

    -- Do your work...
END

Alternative

Wie in einem Kommentar von RBarryYoung ausgeführt , können Sie dieses Problem zunächst verhindern, indem Sie rekursive Trigger deaktivieren.

Codierung von Yoshi
quelle