2009-04-02 9 views
15

में रिकर्सिव ट्रिगर को रोकें ट्रिगर के पुनरावर्ती निष्पादन को कैसे रोकें? मान लीजिए कि मैं खाते के चार्ट पर "पेड़-सक्षम" विवरण बनाना चाहता हूं। तो मैं क्या करता हूं जब एक नया रिकॉर्ड डाला/अपडेट किया जाता है, तो मैं अभिभावक रिकॉर्ड के down_qty को अद्यतन करता हूं, इसलिए यह अद्यतन ट्रिगर को दोबारा ट्रिगर करेगा।PostgreSQL

अभी, मेरे कोड ठीक है - मैं UPDATE ट्रिगर की पहली लाइन पर डाल:

-- prevents recursive trigger 
if new.track_recursive_trigger <> old.track_recursive_trigger then 
    return new; 
end if; 

और जब मैं माता पिता के रिकॉर्ड की मात्रा को अपडेट करना होगा यह मेरा ट्रिगर से नमूना कोड है:

update account_category set 
    track_recursive_trigger = track_recursive_trigger + 1, -- i put this line to prevent recursive trigger 
    down_qty = down_qty - (old.down_qty + 1) 
where account_category_id = m_parent_account; 

मैं सोच रहा हूं कि पोस्टग्रेएसक्यूएल में एक नया क्षेत्र शुरू किए बिना रिकर्सिव ट्रिगर का पता लगाने के लिए कोई तरीका है, एमएसएसक्यूएल के trigger_nestlevel के समान कुछ।

[संपादित करें]

मैं पेड़ के अंदर पाश, मैं बबल सामने प्रत्येक account_category वापस उसकी जड़ के down_qty की जरूरत है। उदाहरण के लिए, मैं एक नया खाता श्रेणी, यह जब मैं खाता श्रेणी के माता-पिता account_category बदल अपनी मूल account_category की down_qty बढ़ाने के लिए की जरूरत है, वैसे ही डालें, मैं account_category के पिछले माता पिता account_category की down_qty घटती की जरूरत है। हालांकि मुझे लगता है कि यह कर सकता है, मैं PostgreSQL को रिकर्सिव ट्रिगर नहीं दे रहा हूं। मैंने एमएसएसएलएल का उपयोग किया था, जहां ट्रिगर रिकर्सिव गहराई का स्तर केवल 16 स्तर तक ही सीमित है।

+1

मुझे लगता है कि आप थोड़ा में अधिक जानकारी के व्याख्या करनी चाहिए, जहाँ तक मैं देख सकता हूँ वहाँ यहाँ में पुनरावर्ती कॉल का कोई खतरा नहीं है, क्योंकि जब तक आप या तो : रिकॉर्ड जो अपने माता-पिता हैं, या आपके पेड़ में लूप (जो तब पेड़ नहीं है)। –

उत्तर

6

पीजी में, ट्रिगर रिकर्सन को ट्रैक करने के लिए आप पर निर्भर है। एक ट्रिगर समारोह आदेशों को निष्पादित करता

तो एसक्यूएल तो इन आदेशों हो सकता है आग फिर से चलाता है। इसे कैस्केडिंग ट्रिगर के रूप में जाना जाता है। कैस्केड स्तरों की संख्या पर कोई प्रत्यक्ष सीमा नहीं है। पर कैस्केड के लिए यह संभव है समान ट्रिगर का एक पुनरावर्ती आमंत्रण; उदाहरण के लिए, एक INSERT ट्रिगर एक कमांड निष्पादित कर सकता है जो समान तालिका में एक अतिरिक्त पंक्ति डालता है, जिससे INSERT ट्रिगर फिर से निकाला जा सकता है। यह प्रोग्रामर की ज़िम्मेदारी ऐसे परिदृश्यों में अनंत रिकर्सन से बचने के लिए है।

http://www.postgresql.org/docs/8.3/static/trigger-definition.html

3

ट्रिगर की परिभाषा की शुरुआत में आप उस विशेष मेज पर चलाता निष्क्रिय कर सकते हैं, और उन्हें अंत में पुन: सक्षम (और उम्मीद से पहले सुनिश्चित करें कि एक अपवाद निष्पादन समाप्त नहीं करता है!)। इसमें कई गहरे छेद हैं, लेकिन कुछ हल्के कार्यान्वयन के लिए काम कर सकते हैं। ध्यान दें कि इस कार्यान्वयन के लिए, आपको ट्रिगर्स को अक्षम करने के लिए निजीकरण की भी आवश्यकता होगी।

+0

यह काम नहीं करता है, क्योंकि: तालिका को "ट्रिगर_टेबल" नहीं बदल सकता क्योंकि इसका उपयोग इस सत्र में सक्रिय प्रश्नों द्वारा किया जा रहा है –

54

मैं पोस्टग्रेएसक्यूएल 9.2 में यही करता हूं, हालांकि मुझे यह स्वीकार करना होगा कि मुझे इस दृष्टिकोण को दस्तावेज नहीं मिला है। एक फ़ंक्शन pg_trigger_depth()documented here है, जिसका उपयोग मैं ट्रिगर में मूल और नेस्टेड कॉल के बीच अंतर करने के लिए करता हूं।

CREATE TRIGGER trg_taxonomic_positions 
AFTER INSERT OR UPDATE OF taxonomic_position 
ON taxon_concepts 
FOR EACH ROW 
WHEN (pg_trigger_depth() = 0) 
EXECUTE PROCEDURE trg_taxonomic_positions() 
+0

अच्छा खोज! यह अन्यथा कांटेदार समस्याओं का एक मेजबान हल करने में मदद करता है। –

+0

स्कोर! बिल्कुल सही समाधान, धन्यवाद! – theory

+4

शानदार! दुर्भाग्यवश, यह फ़ंक्शन 9.1 :(में मौजूद नहीं है। मुझे आश्चर्य है कि इसके लिए कोई प्रतिस्थापन है ... – mvp

2

असंबद्ध रिकर्सन से बचने के लिए, my answer here देखें।जैसा कि अन्य ने टिप्पणी की है, यदि आपकी डेटा संरचना एक असली पेड़ है (रूट (ओं) में कोई अभिभावक नहीं होगा) और रिकर्सन रूट पर को हमेशा रोक देगा। नोड केवल एक पैरेंट पॉइंटर के साथ, लापरवाही के लिए एकमात्र तरीका होगा यदि लूप मौजूद थे। (मेरी कड़ी में विधि सबसे पर किसी भी नोड का दौरा करेंगे एक बार)