एक दो अंक। सबसे पहले, आप स्वायत्त लेनदेन प्रज्ञा का दुरुपयोग कर रहे हैं। यह अलग लेनदेन के लिए है जिसे आपको मुख्य लेनदेन से स्वतंत्र रूप से प्रतिबद्ध या रोलबैक करने की आवश्यकता है। आप इसका उपयोग मुख्य लेन-देन को रोलबैक करने के लिए कर रहे हैं -- और यदि कोई त्रुटि नहीं है तो आप कभी भी प्रतिबद्ध नहीं हैं।
और उन "अप्रत्याशित परिणामों" का किसी ने उल्लेख किया है? उनमें से एक यह है कि आपकी गिनती हमेशा 0 लौटाती है। इसलिए प्रज्ञा दोनों को हटा दें क्योंकि इसका दुरुपयोग किया जा रहा है और इसलिए गिनती उचित मूल्य लौटाएगी।
एक और बात ट्रिगर्स के भीतर कमिट या रोलबैक नहीं है। एक त्रुटि उठाएँ और नियंत्रण कोड को वह करने दें जो उसे करने की आवश्यकता है। मुझे पता है कि रोलबैक प्रगति के कारण थे। प्रज्ञा को हटाते समय बस उन्हें हटाना न भूलें।
निम्नलिखित ट्रिगर मेरे लिए काम करता है:
CREATE OR REPLACE TRIGGER trg_mytable_biu
BEFORE INSERT OR UPDATE ON mytable
FOR EACH ROW
WHEN (NEW.TYPEB = 'Bert') -- Don't even execute unless this is Bert
DECLARE
L_COUNT NUMBER;
BEGIN
SELECT COUNT(*) INTO L_COUNT
FROM MYTABLE
WHERE ARTICLE = :NEW.ARTICLE
AND TYPEB = :NEW.TYPEB;
IF L_COUNT > 0 THEN
RAISE_APPLICATION_ERROR( -20001, 'Bert already exists!' );
ELSIF :NEW.STOCK_COUNT > 1 THEN
RAISE_APPLICATION_ERROR( -20001, 'Can''t insert more than one Bert!' );
END IF;
END;
हालांकि, किसी तालिका पर ट्रिगर के लिए उस तालिका को अलग से एक्सेस करना एक अच्छा विचार नहीं है। आमतौर पर सिस्टम इसकी अनुमति भी नहीं देगा -- अगर इसे "बाद" में बदल दिया जाए तो यह ट्रिगर बिल्कुल भी निष्पादित नहीं होगा। यदि इसे निष्पादित करने की अनुमति दी जाती है, तो कोई भी प्राप्त परिणामों के बारे में सुनिश्चित नहीं हो सकता - जैसा कि आप पहले ही जान चुके हैं। दरअसल, मैं थोड़ा हैरान हूं कि उपरोक्त ट्रिगर काम करता है। मैं इसे वास्तविक डेटाबेस में उपयोग करने में असहज महसूस करूंगा।
सबसे अच्छा विकल्प जब एक ट्रिगर जरूरी लक्ष्य तालिका तक पहुंच एक दृश्य के पीछे तालिका को छिपाने के लिए है और दृश्य पर "के बजाय" ट्रिगर लिखना है। वह ट्रिगर अपनी इच्छानुसार तालिका तक पहुँच सकता है।