Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A következőkre vonatkozik:SQL Server
Azure SQL Database
Felügyelt Azure SQL-példány
SQL-adatbázis a Microsoft Fabricben
A DML és a DDL-eseményindítók is beágyazottak, amikor egy eseményindító egy másik eseményindítót kezdeményező műveletet hajt végre. Ezek a műveletek más eseményindítókat is elindíthatnak, és így tovább. A DML- és DDL-eseményindítók legfeljebb 32 szintbe ágyazhatók. Beállíthatja, hogy az AFTER-eseményindítók beágyazhatók-e a beágyazott eseményindítókon kiszolgálókonfigurációs beállításon keresztül. Az INSTEAD OF eseményindítók (amelyek csak DML eseményindítók lehetnek) ettől a beállítástól függetlenül beágyazhatók.
Jegyzet
Az Transact-SQL-eseményindítók által kezelt kódra való hivatkozás egy szintnek számít a 32 szintű beágyazási korláttal szemben. A felügyelt kódból meghívott metódusok nem számítanak bele ebbe a korlátba.
Ha a beágyazott eseményindítók engedélyezettek, és a lánc egyik eseményindítója végtelen ciklust indít el, a rendszer túllépi a beágyazási szintet, és az eseményindító leáll.
Beágyazott eseményindítók használatával hasznos takarítási funkciókat hajthat végre, például egy korábbi eseményindító által érintett sorok biztonsági másolatának tárolását. Létrehozhat például egy eseményindítót PurchaseOrderDetail, amely menti a PurchaseOrderDetail sorokat, amelyeket az delcascadetrig eseményindító törölt. A delcascadetrig eseményindító hatályba lépésekor az 1965-ös PurchaseOrderID törlése a PurchaseOrderHeader-ből törli a megfelelő sort vagy sorokat PurchaseOrderDetail-ból. Az adatok mentéséhez létrehozhat egy DELETE eseményindítót PurchaseOrderDetail, amely a törölt adatokat egy másik, külön létrehozott táblába menti, del_save. Például:
CREATE TRIGGER Purchasing.savedel
ON Purchasing.PurchaseOrderDetail
FOR DELETE
AS
INSERT del_save
SELECT * FROM deleted;
Nem javasoljuk, hogy beágyazott eseményindítókat használjon sorrendfüggő sorrendben. Használjon külön eseményindítókat az adatmódosítások kaszkádoltká alakításához.
Jegyzet
Mivel az eseményindítók egy tranzakción belül futnak, a beágyazott eseményindítók bármelyik szintjén bekövetkező hiba megszakítja a teljes tranzakciót, és az összes adatmódosítás vissza lesz állítva. A PRINT utasításokat az eseményindítókba is belefoglalhatja, hogy megállapíthassa, hol történt a hiba.
Rekurzív indítók
Az AFTER eseményindító nem hívja meg magát rekurzívan, hacsak nincs beállítva a RECURSIVE_TRIGGERS adatbázis-beállítás.
A rekurziónak két típusa van:
Közvetlen rekurzió
Ez a rekurzió akkor fordul elő, ha egy eseményindító aktiválódik, és olyan műveletet hajt végre, amely ugyanazt az eseményindítót ismét aktiválja. Például egy alkalmazás frissíti a T3táblázatot; ez okozza, hogy Trig3 aktiválódik. Trig3 frissíti a T3 táblát újra; ez okozza, hogy a Trig3 újra aktiválódik.
Közvetlen rekurzió akkor is előfordulhat, ha ugyanazt az eseményindítót újra meghívják, de egy másik típusú eseményindító (AFTER vagy HELYETTE) meghívása után. Más szóval, egy HELYETT eseményindító közvetlen rekurziója akkor fordulhat elő, ha ugyanazt a HELYETT eseményindítót másodszor is meghívják, még akkor is, ha a két hívás között egy vagy több AFTER eseményindítót is meghívnak. Hasonlóképpen, az AFTER trigger közvetlen rekurziója akkor fordulhat elő, ha ugyanaz az AFTER trigger másodszor is meghívásra kerül, még akkor is, ha egy vagy több INSTEAD OF triggert hívnak meg közben. Például egy alkalmazás frissíti a T4táblát. Ez a frissítés okozza az INSTEAD OF trigger (Trig4) aktiválódását. Trig4 frissíti a táblát T5. Ez a frissítés az AFTER trigger Trig5 aktiválódását okozza. Trig5 frissíti a T4 táblát, és ez a frissítés ismételten aktiválja az INSTEAD OF triggert, Trig4. Ezt az eseményláncot Trig4közvetlen rekurziójának tekintik.
Közvetett rekurzió
Ez a rekurzió akkor fordul elő, ha egy eseményindító aktiválódik, és olyan műveletet hajt végre, amely egy másik, azonos típusú eseményindítót indít el (AFTER vagy HELYETTE). Ez a második eseményindító olyan műveletet hajt végre, amely miatt az eredeti eseményindító újra aktiválódik. Más szóval, közvetett rekurzió akkor fordulhat elő, ha a rendszer másodszor is meghív egy INSTEAD OF trigger-t, de csak akkor, ha közben már meghívtak egy másik INSTEAD OF trigger-t. Hasonlóképpen, a közvetett rekurzió akkor fordulhat elő, ha egy AFTER eseményindítót második alkalommal hív meg, de addig nem, amíg egy másik AFTER eseményindítót nem hív be a kettő között. Például egy alkalmazás frissíti a T1táblát. Ez a frissítés az AFTER trigger Trig1 aktiválódását okozza. Trig1 frissíti a táblázatot T2, és ez a frissítés miatt az utáni eseményindító Trig2 aktivál. Trig2 viszont frissíti a táblázatot T1, amely miatt a AFTER trigger Trig1 újra kigyullad.
Csak a AFTER-eseményindítók közvetlen rekurziója lesz megakadályozva, ha a RECURSIVE_TRIGGERS adatbázis beállítása KI értékre van állítva. A AFTER triggerek közvetett rekurziójának letiltásához állítsa a beágyazott triggerek kiszolgáló opciót 0értékre.
Példák
Az alábbi példa rekurzív eseményindítók használatát mutatja be egy önhivatkozási kapcsolat (más néven tranzitív lezárás) megoldásához. A emp_mgr tábla például a következőket határozza meg:
Egy vállalat alkalmazottja (
emp).Az egyes alkalmazottak vezetője (
mgr).Minden egyes alkalmazottnak a szervezeti fában hozzá tartozóan jelentett alkalmazottak teljes száma (
NoOfReports).
Rekurzív UPDATE-triggert használhat az NoOfReports oszlop up-todátumának frissítésére, amikor új alkalmazotti rekordokat szúr be. Az INSERT eseményindító frissíti a kezelőrekord NoOfReports oszlopát, amely rekurzív módon frissíti a felügyeleti hierarchia többi rekordjának NoOfReports oszlopát.
USE AdventureWorks2022;
GO
-- Turn recursive triggers ON in the database.
ALTER DATABASE AdventureWorks2022
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
Íme a frissítés előtti eredmények.
emp mgr NoOfReports
------------------------------ ----------------------------- -----------
Alice Harry 2
Dave Joe 0
Harry NULL 1
Joe Alice 1
Paul Alice 0
Íme a frissítés utáni eredmények.
emp mgr NoOfReports
------------------------------ ----------------------------- -----------
Alice Harry 2
Dave Harry 0
Harry NULL 2
Joe Alice 0
Paul Alice 0
Beágyazott eseményindítók beállítása
Az RECURSIVE_TRIGGERS adatbázis beállításának beállítása
Lásd még:
LÉTREHOZNI TRIGGERET (Transact-SQL)
Beágyazott eseményindítók konfigurálása kiszolgálókonfigurációs beállítás