Megosztás a következőn keresztül:


Beágyazott eseményindítók létrehozása

A következőkre vonatkozik:SQL ServerAzure SQL DatabaseFelügyelt Azure SQL-példánySQL-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