Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Sowohl DML- als auch DDL-Trigger werden geschachtelt, wenn ein Trigger eine Aktion ausführt, die einen anderen Trigger initiiert. Diese Aktionen können andere Trigger initiieren usw. DML- und DDL-Trigger können bis zu 32 Ebenen geschachtelt werden. Sie können steuern, ob AFTER-Trigger über die Geschachtelte Serverkonfigurationsoption geschachtelt werden können. ANSTELLE VON Triggern (nur DML-Trigger können ANSTELLE VON Triggern) unabhängig von dieser Einstellung geschachtelt werden.
Hinweis
Jeder Verweis auf verwalteten Code aus einem Transact-SQL Trigger zählt als eine Ebene für die 32-Ebenen-Schachtelungsgrenze. Methoden, die aus verwaltetem Code aufgerufen werden, zählen nicht für diesen Grenzwert.
Wenn geschachtelte Trigger zulässig sind und ein Trigger in der Kette eine Endlosschleife startet, wird die Schachtelungsebene überschritten und der Trigger beendet.
Sie können geschachtelte Trigger verwenden, um nützliche Housekeepingfunktionen auszuführen, z. B. das Speichern einer Sicherungskopie von Zeilen, die von einem vorherigen Trigger betroffen sind. Sie können z. B. einen Trigger PurchaseOrderDetail erstellen, der eine Sicherungskopie der Zeilen speichert, die PurchaseOrderDetail der delcascadetrig Trigger gelöscht hat. Mit dem delcascadetrig tatsächlichen Auslöser löscht das Löschen PurchaseOrderID von PurchaseOrderHeader 1965 die entsprechende Zeile oder Zeile aus PurchaseOrderDetail. Zum Speichern der Daten können Sie einen DELETE-Trigger PurchaseOrderDetail erstellen, der die gelöschten Daten in einer anderen separat erstellten Tabelle speichert. del_save Beispiel:
CREATE TRIGGER Purchasing.savedel
ON Purchasing.PurchaseOrderDetail
FOR DELETE
AS
INSERT del_save;
SELECT * FROM deleted;
Es wird nicht empfohlen, geschachtelte Trigger in einer reihenfolgeabhängigen Sequenz zu verwenden. Verwenden Sie separate Trigger, um Datenänderungen zu überlappen.
Hinweis
Da Trigger innerhalb einer Transaktion ausgeführt werden, bricht ein Fehler auf jeder Ebene geschachtelter Trigger die gesamte Transaktion ab, und alle Datenänderungen werden zurückgesetzt. Fügen Sie PRINT-Anweisungen in Ihre Trigger ein, damit Sie bestimmen können, wo der Fehler aufgetreten ist.
Rekursive Trigger
Ein AFTER-Trigger ruft sich nicht rekursiv auf, es sei denn, die RECURSIVE_TRIGGERS Datenbankoption ist festgelegt.
Es gibt zwei Arten von Rekursionen:
Direkte Rekursion
Diese Rekursion tritt auf, wenn ein Trigger ausgelöst wird und eine Aktion ausführt, die denselben Trigger erneut auslöst. Beispielsweise aktualisiert eine Anwendung die Tabelle T3; dies bewirkt, dass Trig3 ausgelöst wird. Trig3 aktualisiert die Tabelle T3 erneut; dies bewirkt, dass Trig3 erneut ausgelöst wird.
Direkte Rekursion kann auch auftreten, wenn derselbe Trigger erneut aufgerufen wird, jedoch nachdem ein Trigger eines anderen Typs (AFTER oder INSTEAD OF) ausgelöst wurde. Mit anderen Worten, direkte Rekursion eines INSTEAD OF-Triggers kann auftreten, wenn derselbe INSTEAD OF-Trigger ein zweites Mal aufgerufen wird, auch wenn ein oder mehrere AFTER-Trigger dazwischen aufgerufen werden. Ebenso kann die direkte Rekursion eines AFTER-Triggers auftreten, wenn derselbe AFTER-Trigger erneut aufgerufen wird, selbst wenn ein oder mehrere INSTEAD OF-Trigger dazwischen aufgerufen werden. Beispielsweise aktualisiert eine Anwendung die Tabelle T4. Dieses Update bewirkt, dass der INSTEAD OF-Trigger Trig4 ausgelöst wird. Trig4 aktualisiert Tabelle T5. Dieses Update bewirkt, dass AFTER Trig5 ausgelöst wird. Trig5 aktualisiert tabelle T4, und dieses Update bewirkt, dass Trig4 erneut ausgelöst wird. Diese Ereigniskette gilt als direkte Rekursion für Trig4.
Indirekte Rekursion
Diese Rekursion tritt auf, wenn ein Trigger ausgelöst wird und eine Aktion ausführt, die dazu führt, dass ein anderer Trigger desselben Typs (AFTER oder INSTEAD OF) aktiviert wird. Dieser zweite Trigger führt eine Aktion aus, die bewirkt, dass der ursprüngliche Trigger erneut ausgelöst wird. Mit anderen Worten, indirekte Rekursion kann auftreten, wenn ein INSTEAD OF-Trigger ein zweites Mal aufgerufen wird, aber erst, wenn ein anderer INSTEAD OF-Trigger dazwischen aufgerufen wird. Ebenso kann eine indirekte Rekursion auftreten, wenn ein AFTER-Trigger ein zweites Mal aufgerufen wird, aber erst, nachdem zwischendurch ein anderer AFTER-Trigger aufgerufen wurde. Beispielsweise aktualisiert eine Anwendung die Tabelle T1. Dieses Update bewirkt, dass AFTER-Trigger Trig1 ausgelöst wird. Trig1 aktualisiert die Tabelle T2, und dieses Update bewirkt, dass AFTER-Trigger Trig2 ausgelöst wird. Trig2 aktualisiert wiederum die Tabelle T1 , die bewirkt, dass AFTER-Trigger Trig1 erneut ausgelöst wird.
Nur die direkte Rekursion der AFTER-Trigger wird verhindert, wenn die Datenbankoption RECURSIVE_TRIGGERS auf OFF gesetzt ist. Um die indirekte Rekursion von AFTER-Triggern zu deaktivieren, legen Sie auch die Option für geschachtelte Trigger auf 0 fest.
Beispiele
Das folgende Beispiel zeigt die Verwendung rekursiver Trigger zum Lösen einer selbstverweisenden Beziehung (auch als transitive Schließung bezeichnet). Die Tabelle emp_mgr definiert beispielsweise Folgendes:
Ein Mitarbeiter (
emp) in einem Unternehmen.Der Vorgesetzte für jeden Mitarbeiter (
mgr).Die Gesamtzahl der Mitarbeiter in der Organisationsstruktur, die für jeden Mitarbeiter (
NoOfReports) gemeldet wird.
Ein rekursiver UPDATE-Trigger kann verwendet werden, um die NoOfReports Spalte up-to-datum beizubehalten, wenn neue Mitarbeiterdatensätze eingefügt werden. Der INSERT-Trigger aktualisiert die NoOfReports-Spalte des Managerdatensatzes, wodurch die NoOfReports-Spalte anderer Datensätze rekursiv innerhalb der Management-Hierarchie aktualisiert wird.
USE AdventureWorks2012;
GO
-- Turn recursive triggers ON in the database.
ALTER DATABASE AdventureWorks2012
SET RECURSIVE_TRIGGERS ON;
GO
CREATE TABLE dbo.emp_mgr (
emp char(30) PRIMARY KEY,
mgr char(30) NULL FOREIGN KEY REFERENCES emp_mgr(emp),
NoOfReports int DEFAULT 0
);
GO
CREATE TRIGGER dbo.emp_mgrins ON dbo.emp_mgr
FOR INSERT
AS
DECLARE @e char(30), @m char(30);
DECLARE c1 CURSOR FOR
SELECT emp_mgr.emp
FROM emp_mgr, inserted
WHERE emp_mgr.emp = inserted.mgr;
OPEN c1;
FETCH NEXT FROM c1 INTO @e;
WHILE @@fetch_status = 0
BEGIN
UPDATE dbo.emp_mgr
SET emp_mgr.NoOfReports = emp_mgr.NoOfReports + 1 -- Add 1 for newly
WHERE emp_mgr.emp = @e ; -- added employee.
FETCH NEXT FROM c1 INTO @e;
END
CLOSE c1;
DEALLOCATE c1;
GO
-- This recursive UPDATE trigger works assuming:
-- 1. Only singleton updates on emp_mgr.
-- 2. No inserts in the middle of the org tree.
CREATE TRIGGER dbo.emp_mgrupd ON dbo.emp_mgr FOR UPDATE
AS
IF UPDATE (mgr)
BEGIN
UPDATE dbo.emp_mgr
SET emp_mgr.NoOfReports = emp_mgr.NoOfReports + 1 -- Increment mgr's
FROM inserted -- (no. of reports) by
WHERE emp_mgr.emp = inserted.mgr; -- 1 for the new report.
UPDATE dbo.emp_mgr
SET emp_mgr.NoOfReports = emp_mgr.NoOfReports - 1 -- Decrement mgr's
FROM deleted -- (no. of reports) by 1
WHERE emp_mgr.emp = deleted.mgr; -- for the new report.
END
GO
-- Insert some test data rows.
INSERT dbo.emp_mgr(emp, mgr) VALUES
('Harry', NULL)
,('Alice', 'Harry')
,('Paul', 'Alice')
,('Joe', 'Alice')
,('Dave', 'Joe');
GO
SELECT emp,mgr,NoOfReports
FROM dbo.emp_mgr;
GO
-- Change Dave's manager from Joe to Harry
UPDATE dbo.emp_mgr SET mgr = 'Harry'
WHERE emp = 'Dave';
GO
SELECT emp,mgr,NoOfReports FROM emp_mgr;
GO
Hier sind die Ergebnisse vor dem Update.
emp mgr NoOfReports
------------------------------ ----------------------------- -----------
Alice Harry 2
Dave Joe 0
Harry NULL 1
Joe Alice 1
Paul Alice 0
Hier sind die Ergebnisse nach dem Update.
emp mgr NoOfReports
------------------------------ ----------------------------- -----------
Alice Harry 2
Dave Harry 0
Harry NULL 2
Joe Alice 0
Paul Alice 0
Um die Option "Geschachtelte Trigger" festzulegen
So legen Sie die RECURSIVE_TRIGGERS-Datenbankoption fest
Siehe auch
CREATE TRIGGER (Transact-SQL)
Konfigurieren der geschachtelten Trigger für die Serverkonfigurationsoption