2009-01-10 10 views
17

मान लें कि आपके पास टेबल Presentations और Events है। जब कोई प्रस्तुति सहेजी जाती है और इसमें मूल ईवेंट जानकारी होती है, जैसे स्थान और दिनांक, एक ईवेंट ट्रिगर का उपयोग करके स्वचालित रूप से बनाया जाएगा। (मुझे डर है कि तकनीकी कारणों के लिए डेटा को केवल एक ही स्थान पर रखना और दृश्य का उपयोग करना असंभव है।) इसके अतिरिक्त, प्रस्तुति में बाद में इस जानकारी को बदलते समय, ट्रिगर घटनाओं को अपडेट पर कॉपी करेगा, जैसे इतना:ट्रिगर्स के पारस्परिक रूप से पुनरावर्ती निष्पादन को रोकें?

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 

अब, ग्राहक यह चाहता है ताकि, एक यूजर कभी घटना में जानकारी परिवर्तित करता है, इसे वापस प्रस्तुति के लिए रूप में अच्छी तरह से जाना चाहिए। स्पष्ट कारणों से, मैं रिवर्स नहीं कर सकता:

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 

आखिरकार, यह प्रत्येक ट्रिगर को एक-दूसरे के बाद आग लगने का कारण बनता है। मैं क्या कर सकता था एक उपयोगकर्ता आईडी युक्त दोनों टेबलों पर last_edit_by कॉलम जोड़ें। एक विशेष अमान्य आईडी के साथ ट्रिगर द्वारा भरा तो (जैसे कि, सकारात्मक वास्तविक व्यक्तियों के सभी उपयोगकर्ता आईडी बनाकर, लेकिन नकारात्मक लिपियों के उपयोगकर्ता आईडी), मैं इस्तेमाल कर सकते हैं कि एक निकास शर्त के रूप में:

AND last_edit_by >= 0 

यह काम हो सकता है , लेकिन मैं जो करना चाहता हूं वह SQL सर्वर को इंगित करता है कि, एक लेनदेन के भीतर, एक ट्रिगर केवल एक बार आग लगाना चाहिए। क्या यह जांचने का कोई तरीका है? या शायद यह जांचने के लिए कि एक तालिका पहले से ही एक ट्रिगर से प्रभावित हो चुकी है?


उत्तर स्टीव रॉबिंस के लिए धन्यवाद:

बस एक अगर हालत trigger_nestlevel() के लिए जाँच में संभावित नेस्ट UPDATE बयान लपेट दें। उदाहरण के लिए:

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 

ध्यान दें कि trigger_nestlevel() जा 1 आधारित प्रतीत होता है, न 0-आधारित। यदि आप दो ट्रिगर्स को एक बार निष्पादित करना चाहते हैं, लेकिन अधिक बार नहीं, तो दोनों ट्रिगर्स में trigger_nestlevel() < 3 देखें।

उत्तर

18

मुझे प्रति लेनदेन करने के बारे में निश्चित नहीं है, लेकिन क्या आपको अन्य भागों के लिए स्विच किए गए नेस्टेड ट्रिगर्स की आवश्यकता है? यदि आप उन्हें सर्वर पर बंद कर देते हैं तो एक ट्रिगर किसी अन्य ट्रिगर से एक टेबल को अपडेट नहीं करेगा।

संपादित करें (टिप्पणियों से जवाब): आप ट्रिगर एक का उपयोग करने के TRIGGER_NESTLEVEL

+0

नेस्टेड चलाता वास्तव में उस डेटाबेस पर अक्षम हैं बदलने के लिए की आवश्यकता होगी। मेरी समस्या एक फायरिंग बी फायरिंग ए ट्रिगर का मामला है, एक फायरिंग ए सीधे नहीं। सेटिंग इसे रोक नहीं देती है। –

+0

रीटर्सिव ट्रिगर्स की बात है, मैं फिलहाल एक मशीन पर नहीं हूं लेकिन मुझे यकीन है कि नेस्टेड ट्रिगर्स भी हैं जिन्हें आप sp_config के साथ कॉन्फ़िगर कर सकते हैं। हालांकि मुझे इस समस्या का सामना करने के कुछ सालों से रहा है। –

+0

आप सही हैं; नेस्टेड ट्रिगर्स एक और विकल्प है। लेकिन जिस तरह से मैंने अपने दस्तावेज़ीकरण को पढ़ा, यह बी को ए के बाद फायरिंग से रोक देगा, जबकि मैं ए को दूसरी बार फायरिंग से रोकना चाहता हूं। –

संबंधित मुद्दे