Aracılığıyla paylaş


İç İçe Tetikleyiciler Oluşturma

Şunlar için geçerlidir:SQL ServerAzure SQL VeritabanıAzure SQL Yönetilen Örneği

Bir tetikleyici başka bir tetikleyici başlatan bir eylem gerçekleştirdiğinde hem DML hem de DDL tetikleyicileri iç içe geçirilir. Bu eylemler diğer tetikleyicileri başlatabilir ve bu şekilde devam edebilir. DML ve DDL tetikleyicileri 32 düzeye kadar iç içe yerleştirilebilir. AFTER tetikleyicilerinin iç içe tetikleyiciler sunucu yapılandırma seçeneği ile iç içe olup olmadığını kontrol edebilirsiniz. Yerine tetikleyiciler (yerine tetikleyiciler yalnızca DML tetikleyicileri olabilir) bu ayardan bağımsız olarak iç içe kullanılabilir.

Not

Bir Transact-SQL tetikleyicisinden yönetimli koda yapılan herhangi bir başvuru, 32 düzeyli iç içe geçme limitine karşı bir düzey olarak sayılır. Yönetilen kodun içinden çağrılan yöntemler bu sınıra karşı sayılmaz.

İç içe tetikleyicilere izin verilirse ve zincirdeki bir tetikleyici sonsuz bir döngü başlatırsa, iç içe geçme düzeyi aşılır ve tetikleyici sonlandırılır.

önceki tetikleyiciden etkilenen satırların yedek kopyasını depolama gibi yararlı temizlik işlevlerini gerçekleştirmek için iç içe geçmiş tetikleyicileri kullanabilirsiniz. Örneğin, delcascadetrig tetikleyicisinin sildiği PurchaseOrderDetail satırlarının yedek kopyasını kaydeden bir PurchaseOrderDetail tetikleyicisi oluşturabilirsiniz. delcascadetrig tetikleyicisi etkinken, PurchaseOrderHeader üzerinde PurchaseOrderID 1965 silindiğinde, ilgili satır veya satırlar PurchaseOrderDetail'den silinir. Verileri kaydetmek için, silinen verileri ayrı olarak oluşturulan başka bir tabloya kaydeden bir DELETE tetikleyicisi PurchaseOrderDetaildel_saveoluşturabilirsiniz. Örneğin:

CREATE TRIGGER Purchasing.savedel  
   ON Purchasing.PurchaseOrderDetail  
FOR DELETE  
AS  
   INSERT del_save
   SELECT * FROM deleted;  

İç içe tetikleyicilerin sıraya bağımlı bir dizide kullanılmasını önermeyiz. Veri değişikliklerini art arda getirmek için ayrı tetikleyiciler kullanın.

Not

Tetikleyiciler bir işlem içinde yürütülürken, iç içe tetikleyici kümesinin herhangi bir düzeyindeki bir hata tüm işlemi iptal eder ve tüm veri değişiklikleri geri alınır. Başarısızlığın oluştuğu yeri belirleyebilmeniz için tetikleyicilerinize PRINT deyimlerini ekleyin.

Özyinelemeli Tetikleyiciler

bir AFTER tetikleyicisi, RECURSIVE_TRIGGERS veritabanı seçeneği ayarlanmadığı sürece özyinelemeli olarak kendisini çağırmaz.

İki tür özyineleme vardır:

  • Doğrudan özyineleme

    Bu özyineleme, bir tetikleyici tetiklendiğinde ve aynı tetikleyicinin yeniden tetiklenmesine neden olan bir eylem gerçekleştirdiğinde oluşur. Örneğin, bir uygulama tablo T3günceller; bu tetikleyici Trig3'ün tetiklenmesine neden olur. Trig3 tablosunu T3 tekrar günceller; bu, tetikleyici Trig3'in tekrar çalışmasına neden olur.

    Doğrudan özyineleme, aynı tetikleyici farklı türde bir tetikleyici (SONRA veya YERİNE) çağrıldıktan sonra yeniden çağrıldığında da oluşabilir. Başka bir deyişle, INSTEAD OF tetikleyicisinin doğrudan özyinelemesi, aralarında bir veya daha fazla AFTER tetikleyicisi çağrılsa bile, aynı INSTEAD OF tetikleyici ikinci kez çağrıldığında meydana gelebilir. Benzer şekilde, aynı AFTER tetikleyicisi ikinci kez çağrıldığında, aralarında bir veya daha fazla YERINE tetikleyici çağrılsa bile, bir AFTER tetikleyicisinin doğrudan özyinelemesi oluşabilir. Örneğin, bir uygulama T4 tablosunu güncelleştirir. Bu güncelleştirme, YERİNE tetikleyici Trig4'in tetiklenmesine neden olur. Trig4 tablo T5güncellemeleri. Bu güncelleştirme Trig5 AFTER tetikleyicisinin tetiklenmesine neden olur. Trig5, T4 tablosunu günceller ve bu güncelleme, INSTEAD OF tetikleyici Trig4'in yeniden tetiklenmesine neden olur. Bu olay zinciri, Trig4için doğrudan özyineleme olarak kabul edilir.

  • Dolaylı özyineleme

    Bu özyineleme, bir tetikleyici tetiklendiğinde ve aynı türde başka bir tetikleyicinin (SONRASI veya YERİNE) tetiklenmesine neden olan bir eylem gerçekleştirdiğinde oluşur. Bu ikinci tetikleyici, özgün tetikleyicinin yeniden tetiklemesine neden olan bir eylem gerçekleştirir. Başka bir deyişle, bir INSTEAD OF tetikleyicisi ikinci kez çağrıldığında dolaylı yeniden çağırma gerçekleşebilir, ancak bu, arada başka bir INSTEAD OF tetikleyicisi çağrılmadan gerçekleşmez. Benzer şekilde, bir AFTER tetikleyicisi ikinci kez çağrıldığında dolaylı özyineleme oluşabilir, ancak arada başka bir AFTER tetikleyicisi çağrılana kadar gerçekleşemez. Örneğin, bir uygulama T1 tablosunu güncelleştirir. Bu güncelleştirme, Trig1 AFTER tetikleyicisinin tetiklenmesine neden olur. Trig1 tablosu T2günceller ve bu güncelleme Trig2 AFTER tetikleyicisini tetikler. Trig2 , T1 tablosunu güncelleştirerek Trig1 ' SONRA tetikleyicisi'nin yeniden tetiklenene.

yalnızca RECURSIVE_TRIGGERS veritabanı seçeneği KAPALI olarak ayarlandığında AFTER tetikleyicilerinin doğrudan özyinelemesi engellenir. AFTER tetikleyicilerinin dolaylı özyinelemini devre dışı bırakmak için, iç içe tetikleyiciler sunucu seçeneğini de 0olarak ayarlayın.

Örnekler

Aşağıdaki örnek, kendi kendine başvuran ilişkiyi çözmek için özyinelemeli tetikleyicileri kullanmayı (geçişli kapanış olarak da bilinir) gösterir. Örneğin, tablo emp_mgr aşağıdakileri tanımlar:

  • Bir şirkette çalışan bir çalışan (emp).

  • Her çalışanın yöneticisi (mgr).

  • Kuruluş ağacındaki her çalışana rapor eden toplam çalışan sayısı (NoOfReports).

Yeni çalışan kayıtları eklendikçe NoOfReports sütununun up-totarihine uygun şekilde güncellenmesini sağlamak için bir özyinelemeli UPDATE tetikleyicisi kullanılabilir. INSERT tetikleyicisi, yönetim hiyerarşisinde diğer kayıtların NoOfReports sütununu yinelemeli olarak güncelleştiren yönetici kaydının NoOfReports sütununu güncelleştirir.

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  

Güncelleştirmeden önceki sonuçlar aşağıdadır.

emp                            mgr                           NoOfReports  
------------------------------ ----------------------------- -----------  
Alice                          Harry                          2  
Dave                           Joe                            0  
Harry                          NULL                           1  
Joe                            Alice                          1  
Paul                           Alice                          0  

Güncelleştirmeden sonraki sonuçlar aşağıdadır.

emp                            mgr                           NoOfReports  
------------------------------ ----------------------------- -----------  
Alice                          Harry                          2  
Dave                           Harry                          0  
Harry                          NULL                           2  
Joe                            Alice                          0  
Paul                           Alice                          0  

İç içe geçmiş tetikleyiciler seçeneğini ayarlamak için

RECURSIVE_TRIGGERS veritabanı seçeneğini ayarlamak için

Ayrıca Bkz.

TETİKLEYİCİ OLUŞTUR (Transact-SQL)
İç içe tetikleyicileri yapılandırma Sunucu Yapılandırma Seçeneği