मेरे पास एक ट्रिगर है जो एक ही समय में हटाकर और सम्मिलित करके तालिका को संशोधित करता है। लेकिन मुझे ORA-00001: unique constraint violated मिल रहा है। मुझे लगता है कि डिलीट कमांड वास्तव में सम्मिलित कमांड को निकाल दिए जाने से पहले नहीं आया था, और क्योंकि मैं एक ट्रिगर के अंदर कमिट का उपयोग नहीं कर सकता, इसलिए मुझे नहीं पता कि उस त्रुटि से कैसे दूर हो।

CREATE OR REPLACE TRIGGER "RESOURCEGROUP_AIU2" 
AFTER INSERT OR UPDATE
ON resourcegroup
BEGIN
FOR ROW IN (SELECT *
             FROM resourcegroup_moves)
LOOP
  IF ROW.oldpath IS NOT NULL
  THEN
     DELETE FROM mayaccessflat 
      WHERE resourceGroup <> inheritedFrom
        AND resourcegroup = ROW.id
        AND inheritedFrom IN (SELECT id
                                FROM resourcegroup
                               WHERE ROW.oldpath LIKE path||'/%');
  END IF;
  INSERT INTO mayaccessflat
             (resourcegroup, person, PROFILE, inheritedfrom)
    SELECT DISTINCT ROW.ID, ma.person, ma.PROFILE, rg.ID
      FROM mayaccess ma, resourcegroup rg
     WHERE ma.resourcegroup = rg.ID
       AND ma.inherit=1
       AND ROW.newpath LIKE rg.PATH || '/%';
END LOOP;
END;

मैं ओरेकल 6 डीबी का उपयोग कर रहा हूं।

0
Thong Vo 19 जुलाई 2018, 06:00
"मैं Oracle 6 DB का उपयोग कर रहा हूं" हम्म, मैं इस तरह के एक प्राचीन अवशेष का उपयोग करने के लिए बधाई कहूंगा लेकिन मुझे नहीं लगता कि आप Oracle v6 का उपयोग कर रहे हैं। मेरे दिमाग को 25 साल पहले कास्टिंग करना, हालांकि ओरेकल 6 ने हमें उन बाधाओं को परिभाषित करने की इजाजत दी जिन्हें वे लागू नहीं किए गए थे: ऐसा ओरेकल 7 तक नहीं हुआ था। इसी तरह ओरेकल 6 में ट्रिगर्स नहीं थे, वे ओरेकल 7 में भी पहुंचे।
 – 
APC
19 जुलाई 2018, 08:59

2 जवाब

समस्या का कमिटमेंट से कोई लेना-देना नहीं है। INSERT उसी लेनदेन में होता है जिसमें DELETE होता है। इसलिए समस्या यह होनी चाहिए कि DELETE उन सभी कुंजियों को नहीं हटा रहा है जिन्हें बाद के कथन द्वारा सम्मिलित किया जा रहा है।

इसका एक कारण यह हो सकता है कि resourcegroup_moves के रिकॉर्ड आंतरिक रूप से एक जैसे नहीं हैं। या हो सकता है कि वे resourcegroup में संबंधित रिकॉर्ड के साथ संगत न हों। यदि ऐसा है, तो INSERT ORA-00001 को सही ढंग से प्रभावित करता है और समाधान resourcegroup_moves के सत्यापन में सुधार होता है।

वैकल्पिक रूप से, हो सकता है कि resourcegroup_moves में रिकॉर्ड्स का सेट मान्य हो, लेकिन असंगतता इसलिए उत्पन्न होती है क्योंकि आप उन रिकॉर्ड्स को एक सेट के बजाय पंक्ति-दर-पंक्ति संसाधित कर रहे हैं। DISTINCT के आपके उपयोग से इसका समाधान नहीं होगा क्योंकि आप पूरे सेट को नहीं संभाल रहे हैं। यदि ऐसा है तो एक सेट-आधारित दृष्टिकोण इसे हल कर सकता है:

CREATE OR REPLACE TRIGGER "RESOURCEGROUP_AIU2" 
AFTER INSERT OR UPDATE
ON resourcegroup
BEGIN
  DELETE FROM mayaccessflat 
  WHERE resourceGroup <> inheritedFrom
  AND (resourcegroup, inheritedFrom) IN 
            (SELECT rgm.id, rg.id
             FROM resourcegroup_moves rgm, 
                   resourcegroup rg
              WHERE rgm.oldpath LIKE rg.path||'/%');

  INSERT INTO mayaccessflat
             (resourcegroup, person, PROFILE, inheritedfrom)
    SELECT DISTINCT rgm.ID, ma.person, ma.PROFILE, rg.ID
      FROM mayaccess ma
           , resourcegroup rg
           , resourcegroup_moves rgm
     WHERE ma.resourcegroup = rg.ID
       AND ma.inherit=1
       AND rgm.newpath LIKE rg.PATH || '/%';
END;

इस तरह के व्यावसायिक तर्क को ट्रिगर में डालना अच्छा अभ्यास नहीं है। यह एक संग्रहित प्रक्रिया के रूप में बेहतर होगा जहां आप resourcegroup और resourcegroup_moves पर सत्यापन नियम लागू कर सकते हैं।

1
APC 19 जुलाई 2018, 08:59

आपको अपनी विशिष्ट बाधा को DEFERRABLE के रूप में सेट करना चाहिए और फिर लेन-देन के अंदर SET CONSTRAINTS name DEFERRED का उपयोग करना चाहिए ताकि लेन-देन किए जाने तक अद्वितीय चेक को स्थगित किया जा सके।

Orcale डॉक्स में विनिर्दिष्ट प्रतिबंध स्थिति देखें।

0
felixbuenemann 19 जुलाई 2018, 06:27