2009-01-10 13 views
17

Presentations ve Events tablolarına sahip olduğunuzu varsayalım. Bir sunum kaydedildiğinde ve konum ve tarih gibi temel olay bilgilerini içerdiğinde, bir tetikleyici kullanılarak otomatik olarak bir olay oluşturulur. (Korkarım ki teknik nedenlerin sadece bir yerde tek bir yerde saklanması ve bir görüş kullanması imkansızdır.) Ayrıca, bu bilgiyi daha sonra sunumda değiştirirken, tetikleyici de güncellemeleri olaya aktarır. gibi pek: bir kullanıcı hiç olay bilgileri değişirse, buna da geri sunum gitmeli, böyleceTetikleyicilerin karşılıklı olarak yinelemeli yürütmesini önler misiniz?

CREATE TRIGGER update_presentations 
ON Presentations 
AFTER UPDATE 
AS 
BEGIN 
    UPDATE Events 
    SET Events.Date = Presentations.Date, 
     Events.Location = Presentations.Location 
    FROM Presentations INNER JOIN Events ON Presentations.EventID = Events.ID 
    WHERE Presentations.ID IN (SELECT ID FROM inserted) 
END 

Şimdi, müşteri bunu istiyor.

CREATE TRIGGER update_events 
ON Events 
AFTER UPDATE 
AS 
BEGIN 
    UPDATE Presentations 
    SET Presentations.Date = Events.Date, 
     Presentations.Location = Events.Location 
    FROM Events INNER JOIN Presentations ON Events.PresentationID = Presentations.ID 
    WHERE Events.ID IN (SELECT ID FROM inserted) 
END 

Sonuçta bu her tetikleyici birbirlerine sonra ateşe neden olur: Bilinen nedenlerden dolayı, ben ters yapamaz. Yapabileceğim şey, bir kullanıcı kimliği içeren her iki tabloya bir sütun last_edit_by eklemektir. (Pozitif gerçek kişilerin tüm kullanıcı kimlikleri yaparak, diyelim ki, ama negatif komut kullanıcı kimlikleri) özel geçersiz kimliğe sahip tetikleyici tarafından doldurulur, bir çıkış koşulu olarak kullanıp olsaydı:

AND last_edit_by >= 0 

Bu işe yarayabilecek ama yapmak istediğim, bir işlem içinde bir tetikleyicinin yalnızca bir kez ateşlenmesi gereken SQL sunucusuna işaret etmek. Bunu kontrol etmenin bir yolu var mı? Ya da belki bir tablonun bir tetikleyici tarafından etkilendiğini kontrol etmek için? Steve Robbins için


Cevap teşekkürler:

Sadece trigger_nestlevel() denetlenirken bir IF durumda potansiyel iç içe UPDATE ifadeleri sarın. Örneğin: trigger_nestlevel() 1-dayanıyor gibi görünüyor bu

CREATE TRIGGER update_presentations 
ON Presentations 
AFTER UPDATE 
AS 
BEGIN 
    IF trigger_nestlevel() < 2 
     UPDATE Events 
     SET Events.Date = Presentations.Date, 
      Events.Location = Presentations.Location 
     FROM Presentations INNER JOIN Events ON Presentations.EventID = Events.ID 
     WHERE Presentations.ID IN (SELECT ID FROM inserted) 
END 

Not, 0 temelli değildir. Her iki tetikleyicinin de bir kez yürütmesini, ancak daha sık olmamasını istiyorsanız, her iki tetikleyicide de trigger_nestlevel() < 3 numarasını kontrol edin.

cevap

18

İşlem başına yaptığınızdan emin değilim, ancak diğer parçalar için iç içe tetiklemeli tetikleyicilere mi ihtiyacınız var? Onları sunucuda kapatırsanız, bir tablo güncellenirken başka bir tetikleyiciden tetikleyici tetiklenmez. (Yorumlardan yanıt)

DÜZENLEME: Sen tetik A TRIGGER_NESTLEVEL

+0

İçiçe tetikleyiciler aslında bu veritabanı üzerinde devre dışı bırakılır kullanmayı değiştirmek gerekecektir. Benim sorunum bir tetikleme A ateşleme A ateş, A ateş değil A doğrudan. Ayar bunu engellemez. –

+0

Bu yinelemeli tetikleyiciler, şu anda bir makinede değilim ama eminim ki sp_config ile yapılandırabileceğiniz iç içe tetikleyiciler var. Yine de bu problemle yüzleştiğim birkaç yıl oldu. –

+0

Haklısınız; iç içe tetikleyiciler başka bir seçenektir. Ama belgelerini okuduğumda, A'dan sonra ateşlemeyi engeller, oysa A'nın ikinci kez ateş etmesini önlemek istiyorum. –

İlgili konular