आपने जो चलाया है वह क्लासिक "म्यूटिंग टेबल" अपवाद है। ROW ट्रिगर में Oracle आपको उस तालिका के विरुद्ध क्वेरी चलाने की अनुमति नहीं देता है जिस पर ट्रिगर परिभाषित किया गया है - इसलिए यह SELECT
है DELETING
. में TABLE1 के सामने ट्रिगर का वह हिस्सा जिसके कारण यह समस्या हो रही है।
इसके आसपास काम करने के कुछ तरीके हैं। शायद इस स्थिति में सबसे अच्छा एक यौगिक ट्रिगर का उपयोग करना है, जो कुछ इस तरह दिखाई देगा:
CREATE OR REPLACE TRIGGER TABLE1_NUM_TRG
FOR INSERT OR DELETE ON TABLE1
COMPOUND TRIGGER
TYPE NUMBER_TABLE IS TABLE OF NUMBER;
tblTABLE2_IDS NUMBER_TABLE;
BEFORE STATEMENT IS
BEGIN
tblTABLE2_IDS := NUMBER_TABLE();
END BEFORE STATEMENT;
AFTER EACH ROW IS
BEGIN
IF INSERTING THEN
UPDATE TABLE2 t2
SET t2.TABLE2NUM = :new.NUM
WHERE t2.ID = :new.TABLE2_ID;
ELSIF DELETING THEN
tblTABLE2_IDS.EXTEND;
tblTABLE2_IDS(tblTABLE2_IDS.LAST) := :new.TABLE2_ID;
END IF;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
IF tblTABLE2_IDS.COUNT > 0 THEN
FOR i IN tblTABLE2_IDS.FIRST..tblTABLE2_IDS.LAST LOOP
UPDATE TABLE2 t2
SET t2.TABLE2NUM = (SELECT NUM
FROM (SELECT t1.NUM
FROM TABLE1 t1
WHERE t1.TABLE2_ID = tblTABLE2_IDS(i)
ORDER BY modification_date DESC)
WHERE ROWNUM = 1)
WHERE t2.ID = tblTABLE2_IDS(i);
END LOOP;
END IF;
END AFTER STATEMENT;
END TABLE1_NUM_TRG;
एक कंपाउंड ट्रिगर प्रत्येक समय बिंदु (BEFORE STATEMENT
. की अनुमति देता है , BEFORE ROW
, AFTER ROW
, और AFTER STATEMENT
) संभाला जाना है। ध्यान दें कि समय बिंदुओं को हमेशा दिए गए क्रम में लागू किया जाता है। जब एक उपयुक्त SQL स्टेटमेंट (यानी INSERT INTO TABLE1
.) या DELETE FROM TABLE1
) निष्पादित किया जाता है और इस ट्रिगर को सक्रिय किया जाता है, जिसे लागू किया जाने वाला पहला समय बिंदु BEFORE STATEMENT
होगा , और कोड BEFORE STATEMENT
. में हैंडलर संख्याओं का एक समूह रखने के लिए पीएल/एसक्यूएल तालिका आवंटित करेगा। इस स्थिति में PL/SQL तालिका में संग्रहीत की जाने वाली संख्याएँ TABLE1 से TABLE2_ID मान होंगी। (उदाहरण के लिए, एक सरणी के बजाय एक PL/SQL तालिका का उपयोग किया जाता है क्योंकि एक तालिका में अलग-अलग संख्या में मान हो सकते हैं, जबकि यदि हम एक सरणी का उपयोग करते हैं तो हमें पहले से पता होना चाहिए कि हमें कितनी संख्याएं संग्रहीत करने की आवश्यकता होगी। हम पहले से नहीं जान सकते कि किसी विशेष कथन से कितनी पंक्तियाँ प्रभावित होंगी, इसलिए हम PL/SQL तालिका का उपयोग करते हैं)।
जब AFTER EACH ROW
समय बिंदु पर पहुंच गया है और हम पाते हैं कि संसाधित किया जा रहा बयान एक INSERT है, ट्रिगर बस आगे बढ़ता है और आवश्यक अद्यतन को TABLE2 में करता है क्योंकि इससे कोई समस्या नहीं होगी। हालाँकि, यदि कोई DELETE किया जा रहा है तो ट्रिगर TABLE1.TABLE2_ID को पहले आवंटित PL/SQL तालिका में सहेजता है। जब AFTER STATEMENT
समय बिंदु अंत में पहुंच गया है, पहले आवंटित पीएल/एसक्यूएल तालिका के माध्यम से पुनरावृत्त किया जाता है, और प्रत्येक TABLE2_ID के लिए उपयुक्त अद्यतन किया जाता है।
दस्तावेज़ीकरण यहाँ।