Za pomocą wyzwalaczy zagnieżdżone
Wyzwalacze zarówno DML, jak i DDL są zagnieżdżone, gdy wyzwalacz wykonuje akcja, który inicjuje wyzwalacz innego.Działania te mogą inicjować innych wyzwalaczy i tak dalej.Wyzwalacze DML i DDL można zagnieździć maksymalnie 32 poziomy.Można kontrolować, czy po Wyzwalacze mogą być zagnieżdżane za pośrednictwem zagnieżdżone wyzwalaczy opcji konfiguracja serwera.Niezależnie od tego ustawienia mogą być zagnieżdżane wyzwalaczy Z INSTEAD (tylko DML Wyzwalacze mogą być zamiast z wyzwalaczy).
Uwaga
Każde odwołanie do kod zarządzany z Transact-SQL wyzwalacz jest liczone jako jeden poziom w ograniczeniu 32 poziomu zagnieżdżenia. Metody wywoływane z kodem zarządzanym nie są uwzględniane przez ten limit.
Dozwolone są zagnieżdżone wyzwalaczy i wyzwalaczy w łańcuchu uruchamia nieskończoną pętlę, poziom zagnieżdżenia został przekroczony i kończy wyzwalacza.
Wyzwalacze zagnieżdżonych służy do wykonywania funkcji gospodarowanie przydatne na przykład przechowywania wierszy dotyczy wyzwalacza poprzedniej kopia zapasowa.Na przykład utworzyć wyzwalacz na PurchaseOrderDetail który zapisuje kopia zapasowa PurchaseOrderDetail wiersze, które delcascadetrig Usunięcie wyzwalacza. Z delcascadetrig w efekcie wyzwalania, usuwanie PurchaseOrderID 1965 roku z PurchaseOrderHeader Usuwa odpowiedni wiersz lub wiersze PurchaseOrderDetail. Aby zapisać dane, można utworzyć wyzwalacza DELETE na PurchaseOrderDetail do innej tabela utworzone oddzielnie, który zapisuje usunięte dane del_save. Na przykład:
CREATE TRIGGER savedel
ON Purchasing.PurchaseOrderDetail
FOR DELETE
AS
INSERT del_save
SELECT * FROM deleted
Nie zaleca się przy użyciu wyzwalaczy zagnieżdżone w sekwencji zależny od zamówienia.Za pomocą oddzielnych wyzwalacze kaskadowo modyfikacji danych.
Uwaga
Ponieważ wykonać wyzwalaczy w obrębie transakcji, awarii na dowolnym poziomie zestaw zagnieżdżonego wyzwalacze anuluje cała transakcja, a wszystkie zmiany danych są przywracane.Dołącz PRINT instrukcji użytkownika wyzwalaczy, aby określić, gdzie wystąpił błąd.
Wyzwalacze cykliczne
Wyzwalacz po nie wywołuje się cyklicznie, chyba że RECURSIVE_TRIGGERS opcji bazy danych jest zestaw.
Istnieją dwa rodzaje rekursję:
Bezpośrednie rekurencji
Rekursję to występuje wtedy, gdy wyzwalacz uruchomieniu i wykonuje akcja, która powoduje, że ten sam wyzwalacz ponownie uruchomienie.Na przykład aplikacja aktualizuje tabela T3; ten wyzwalacz powoduje, że Trig3 uruchomienie.Trig3 aktualizuje tabela T3 ponownie; ten wyzwalacz powoduje, że Trig3 ponownie uruchomienie.
W SQL Server 2008, bezpośrednie rekursja może również wystąpić, gdy ten sam wyzwalacz jest wywoływana ponownie, ale po wyzwalacza innego typu (po lub zamiast) jest wywoływana. Innymi słowy, bezpośrednie rekursji wyzwalacz Z INSTEAD może wystąpić, jeśli taki sam, a nie z wyzwalacz jest wywoływana dla drugiego czas, nawet jeśli jeden lub więcej wyzwalaczy po nazywa się między nimi.Podobnie, bezpośrednie rekursji wyzwalacz po może wystąpić, jeśli taka sama po wyzwalacz jest wywoływana dla drugiego czas, nawet jeśli jeden lub więcej, a nie z wyzwalacze są nazywane między nimi.Na przykład aplikacja aktualizuje tabela T4.Ta aktualizacja powoduje, a nie z wyzwalacza Trig4 uruchomienie.Trig4 aktualizuje tabela T5.Ta aktualizacja powoduje, że po wyzwalacza Trig5 uruchomienie.Trig5 aktualizuje tabela T4, a ta aktualizacja powoduje, że zamiast Z wyzwalaczem Trig4 ponownie uruchomienie.To łańcuch zdarzeń jest uważany za bezpośredniego rekursji do Trig4.
Pośrednie rekurencji
Rekursję to występuje wtedy, gdy wyzwalacz uruchomieniu i wykonuje akcja wywołującą wyzwalacza innym tego samego typu (po lub zamiast) do ognia.Wyzwalacz ten drugi wykonuje akcja wywołującą oryginalnego wyzwalacza ponownie uruchomienie.Innymi słowy, pośrednie rekursja może pojawić się wtedy, gdy wyzwalacz Z INSTEAD jest wywoływana dla drugiego czas, ale nie do drugiego, a nie z wyzwalaczem nazywa się między nimi.Podobnie pośrednie rekursja może pojawić się wtedy, gdy wyzwalacz po jest wywoływana po raz drugi, ale nie do innego po wyzwalacza nazywa się między nimi.Na przykład aplikacja aktualizuje tabela T1.Ta aktualizacja powoduje, że po wyzwalacza Trig1 uruchomienie.Trig1 aktualizuje tabelę TABELA T2, a ta aktualizacja powoduje, że po wyzwalacza Trig2 uruchomienie.Trig2 z kolei aktualizuje tabela T1 powoduje, że po wyzwalacza Trig1 ponownie uruchomienie.
Nie będą mogły tylko bezpośrednie rekursji o później wyzwalaczy, gdy opcja RECURSIVE_TRIGGERS bazy danych jest zestaw na OFF.Wyłączenie rekursji pośrednich z później wyzwalacze, również zestaw zagnieżdżone wyzwalaczy Opcja serwera 0.
Przykłady
W poniższym przykładzie pokazano, przy użyciu wyzwalaczy cyklicznej rozwiązać self-referencing relacji (nazywane także przechodnie zamknięcie).Na przykład w tabela emp_mgr definiuje następujące czynności:
() Pracownikaemp) w firmie.
Menedżera dla każdego pracownika)mgr).
Całkowita liczba pracowników w drzewie organizacji raportowania do każdego pracownika)NoOfReports).
Wyzwalacz UPDATE cyklicznych można używać do przechowywania NoOfReports Kolumna aktualne jako nowego pracownika są wstawiane rekordy. Aktualizacje wyzwalacz INSERT NoOfReports Kolumna rekordu menedżera, który cyklicznie aktualizuje NoOfReports Kolumna innych rekordów w górę hierarchii zarządzania.
USE AdventureWorks;
GO
-- Turn recursive triggers ON in the database.
ALTER DATABASE AdventureWorks
SET RECURSIVE_TRIGGERS ON
GO
CREATE TABLE emp_mgr (
emp char(30) PRIMARY KEY,
mgr char(30) NULL FOREIGN KEY REFERENCES emp_mgr(emp),
NoOfReports int DEFAULT 0
)
GO
CREATE TRIGGER emp_mgrins ON 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 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 emp_mgrupd ON emp_mgr FOR UPDATE
AS
IF UPDATE (mgr)
BEGIN
UPDATE 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 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 emp_mgr(emp, mgr) VALUES ('Harry', NULL)
INSERT emp_mgr(emp, mgr) VALUES ('Alice', 'Harry')
INSERT emp_mgr(emp, mgr) VALUES ('Paul', 'Alice')
INSERT emp_mgr(emp, mgr) VALUES ('Joe', 'Alice')
INSERT emp_mgr(emp, mgr) VALUES ('Dave', 'Joe')
GO
SELECT * FROM emp_mgr
GO
-- Change Dave's manager from Joe to Harry
UPDATE emp_mgr SET mgr = 'Harry'
WHERE emp = 'Dave'
GO
SELECT * FROM emp_mgr
GO
Poniżej przedstawiono wyniki, przed aktualizacją.
emp mgr NoOfReports
------------------------------ ----------------------------- -----------
Alice Harry 2
Dave Joe 0
Harry NULL 1
Joe Alice 1
Paul Alice 0
Poniżej przedstawiono wyniki po aktualizacji.
emp mgr NoOfReports
------------------------------ ----------------------------- -----------
Alice Harry 2
Dave Harry 0
Harry NULL 2
Joe Alice 0
Paul Alice 0
Aby zestaw opcji zagnieżdżonych wyzwalaczy
Aby ustawić opcję RECURSIVE_TRIGGERS bazy danych
See Also