Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Les déclencheurs DML et DDL sont imbriqués lorsqu’un déclencheur effectue une action qui lance un autre déclencheur. Ces actions peuvent lancer d’autres déclencheurs, et ainsi de suite. Les déclencheurs DML et DDL peuvent être imbriqués jusqu’à 32 niveaux. Vous pouvez contrôler dans quelle mesure les déclencheurs AFTER peuvent être imbriqués via l’option de configuration du serveur déclencheurs imbriqués. Les déclencheurs INSTEAD OF (seuls les déclencheurs DML peuvent être des déclencheurs INSTEAD OF) peuvent être imbriqués indépendamment de ce paramètre.
Remarque
Toute référence au code managé à partir d’un déclencheur Transact-SQL compte comme un niveau par rapport à la limite d’imbrication de 32 niveaux. Les méthodes appelées à partir du code managé ne comptent pas sur cette limite.
Si les déclencheurs imbriqués sont autorisés et qu’un déclencheur dans la chaîne démarre une boucle infinie, le niveau d’imbrication est dépassé et le déclencheur se termine.
Vous pouvez utiliser des déclencheurs imbriqués pour effectuer des fonctions de nettoyage utiles, telles que le stockage d’une copie de sauvegarde des lignes affectées par un déclencheur précédent. Par exemple, vous pouvez créer un déclencheur sur PurchaseOrderDetail qui enregistre une copie de sauvegarde des lignes PurchaseOrderDetail que le déclencheur delcascadetrig a supprimées. Avec le déclencheur delcascadetrig en vigueur, supprimer PurchaseOrderID 1965 à partir de PurchaseOrderHeader supprime la ou les lignes correspondantes dans PurchaseOrderDetail. Pour enregistrer les données, vous pouvez créer un déclencheur DELETE sur PurchaseOrderDetail lequel les données supprimées sont enregistrées dans une autre table créée séparément. del_save Par exemple:
CREATE TRIGGER Purchasing.savedel
ON Purchasing.PurchaseOrderDetail
FOR DELETE
AS
INSERT del_save;
SELECT * FROM deleted;
Nous vous déconseillons d’utiliser des déclencheurs imbriqués dans une séquence dépendante de l’ordre. Utilisez des déclencheurs distincts pour effectuer des modifications de données en cascade.
Remarque
Étant donné que les déclencheurs s’exécutent dans une transaction, un échec à tout niveau d’un ensemble de déclencheurs imbriqués annule l’intégralité de la transaction et toutes les modifications de données sont restaurées. Incluez des instructions PRINT dans vos déclencheurs afin de pouvoir déterminer où l’échec s’est produit.
Déclencheurs récursifs
Un déclencheur AFTER ne s'appelle pas de manière récursive, sauf si l'option de base de données RECURSIVE_TRIGGERS est définie.
Il existe deux types de récursivité :
Récursivité directe
Cette récursivité se produit lorsqu’un déclencheur se déclenche et effectue une action qui provoque le déclenchement du même déclencheur. Par exemple, une application met à jour la table T3 ; cela provoque le déclenchement de Trig3 . Trig3 met à jour à nouveau la table T3 ; cela provoque le déclenchement de Trig3 à nouveau.
La récursivité directe peut également se produire lorsque le même déclencheur est appelé à nouveau, mais après un déclencheur d’un autre type (AFTER ou INSTEAD OF) est appelé. En d’autres termes, la récursivité directe d’un déclencheur INSTEAD OF peut se produire lorsque le même déclencheur INSTEAD OF est appelé pour une seconde fois, même si un ou plusieurs déclencheurs AFTER sont appelés entre eux. De même, la récursivité directe d’un déclencheur AFTER peut se produire lorsque le même déclencheur AFTER est appelé pour une seconde fois, même si un ou plusieurs déclencheurs INSTEAD OF sont appelés entre eux. Par exemple, une application met à jour la table T4. Cette mise à jour entraîne le déclenchement du déclencheur INSTEAD OF Trig4 . Trig4 met à jour la table T5. Cette mise à jour entraîne le déclenchement du déclencheur AFTER Trig5 . Trig5 met à jour la table T4, et cette mise à jour provoque à nouveau le déclenchement du déclencheur INSTEAD OF Trig4. Cette chaîne d’événements est considérée comme une récursivité directe pour Trig4.
Récursivité indirecte
Cette récursivité se produit lorsqu’un déclencheur se déclenche et effectue une action qui provoque le déclenchement d’un autre déclencheur du même type (AFTER ou INSTEAD OF). Ce deuxième déclencheur effectue une action qui provoque le déclenchement du déclencheur d’origine à nouveau. En d’autres termes, la récursivité indirecte peut se produire lorsqu’un déclencheur INSTEAD OF est appelé pour une seconde reprise, mais seulement après qu’un autre déclencheur INSTEAD OF ait été appelé entre-temps. De même, la récursivité indirecte peut se produire lorsqu’un déclencheur AFTER est appelé pour une deuxième fois, mais pas avant qu’un autre déclencheur AFTER soit appelé entre-temps. Par exemple, une application met à jour la table T1. Cette mise à jour entraîne le déclenchement du déclencheur AFTER Trig1 . Trig1 met à jour la table T2 et cette mise à jour entraîne le déclenchement du déclencheur AFTER Trig2 . Trig2 met à jour la table T1, ce qui provoque le déclenchement à nouveau du déclencheur AFTER Trig1.
Seule la récursivité directe des déclencheurs AFTER est empêchée lorsque l’option de base de données RECURSIVE_TRIGGERS est définie sur OFF. Pour désactiver la récursivité indirecte des déclencheurs AFTER, définissez également l’option de serveur des déclencheurs imbriqués sur 0.
Exemples
L’exemple suivant montre l’utilisation de déclencheurs récursifs pour résoudre une relation d’auto-référencement (également appelée fermeture transitive). Par exemple, la table emp_mgr définit les éléments suivants :
Un employé (
emp) dans une entreprise.Responsable de chaque employé (
mgr).Nombre total d’employés dans la structure organisationnelle relevant de chaque employé (
NoOfReports).
Un déclencheur UPDATE récursif peut être utilisé pour conserver la NoOfReports colonne up-to-date à mesure que les nouveaux enregistrements d’employés sont insérés. Le déclencheur INSERT met à jour la NoOfReports colonne de l’enregistrement du gestionnaire, qui met à jour de manière récursive la NoOfReports colonne d’autres enregistrements dans la hiérarchie de gestion.
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
Voici les résultats avant la mise à jour.
emp mgr NoOfReports
------------------------------ ----------------------------- -----------
Alice Harry 2
Dave Joe 0
Harry NULL 1
Joe Alice 1
Paul Alice 0
Voici les résultats après la mise à jour.
emp mgr NoOfReports
------------------------------ ----------------------------- -----------
Alice Harry 2
Dave Harry 0
Harry NULL 2
Joe Alice 0
Paul Alice 0
Pour configurer l'option de déclencheurs imbriqués
Pour définir l’option de base de données RECURSIVE_TRIGGERS
Voir aussi
CRÉER UN DÉCLENCHEUR (Transact-SQL)
Configurer l’option de configuration du serveur des déclencheurs imbriqués