Oracle
 sql >> डेटाबेस >  >> RDS >> Oracle

ओरेकल ट्रिगर डालने या हटाने के बाद

आपने जो चलाया है वह क्लासिक "म्यूटिंग टेबल" अपवाद है। 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 के लिए उपयुक्त अद्यतन किया जाता है।

दस्तावेज़ीकरण यहाँ।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle SQL डेवलपर में क्वेरी निष्पादन समय कैसे खोजें?

  2. यदि पहला कॉलम मान समान है तो दूसरे कॉलम मान को कॉनकैट करें

  3. R12.2 . में मैनेज सर्वर कैसे जोड़ें

  4. dbms_output.put_line

  5. मैं संग्रहीत प्रक्रिया से प्रभावित रिकॉर्ड्स की संख्या कैसे प्राप्त कर सकता हूं?