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

Oracle में READONLY कॉलम बनाने का सबसे आसान तरीका क्या है?

यदि चाइल्ड टेबल ऐसे डेटा से भरे हुए हैं जो INITIATIVEID . का संदर्भ देते हैं कॉलम, Oracle को माता-पिता की प्राथमिक कुंजी को बदलकर आपको अनाथ पंक्तियों को बनाने से रोककर प्राथमिक कुंजी मान को स्वचालित रूप से बदलना मुश्किल बना देना चाहिए। इसलिए, उदाहरण के लिए, यदि कोई चाइल्ड टेबल है जिसमें TPM_INITIATIVES के लिए एक विदेशी कुंजी बाधा है और इस चाइल्ड टेबल में INITIATIVEID . के साथ एक पंक्ति है 17 में से, आप INITIATIVEID . को नहीं बदल पाएंगे TPM_INITIAITVES . में पंक्ति का तालिका जिसका वर्तमान मान 17 है। यदि किसी चाइल्ड तालिका में कोई पंक्ति नहीं है जो TPM_INITIATIVES में विशेष पंक्ति को संदर्भित करती है तालिका में, आप मान बदल सकते हैं लेकिन, संभवतः, यदि कोई संबंध नहीं हैं, तो प्राथमिक कुंजी मान को बदलना महत्वहीन है क्योंकि यह परिभाषा के अनुसार, डेटा अखंडता समस्या का कारण नहीं बन सकता है। बेशक, आपके पास कोड हो सकता है जो TPM_INITIATIVES में एक नई पंक्ति सम्मिलित करता है एक नए INITIATIVEID . के साथ , चाइल्ड टेबल में उन सभी पंक्तियों को बदलें जो नई पंक्ति को संदर्भित करने के लिए पुरानी पंक्ति को संदर्भित करती हैं, फिर पुरानी पंक्ति को संशोधित करें। लेकिन यह किसी भी प्रस्तावित समाधान में नहीं फंसेगा।

यदि आपके एप्लिकेशन ने चाइल्ड टेबल को परिभाषित किया है, लेकिन उपयुक्त विदेशी कुंजी बाधाओं को घोषित नहीं किया है, तो यह समस्या को हल करने का सबसे अच्छा तरीका होगा।

ऐसा कहा जा रहा है कि, एक दृश्य बनाने का अर्नोन का समाधान काम करना चाहिए। आप तालिका का नाम बदलें, मौजूदा तालिका के समान नाम के साथ एक दृश्य बनाएं, और (संभावित रूप से) उस दृश्य पर ट्रिगर के INSTEAD को परिभाषित करें जो कभी भी INITIATIVEID को अपडेट नहीं करेगा। कॉलम। इसके लिए एप्लिकेशन के अन्य बिट्स में बदलाव की आवश्यकता नहीं होनी चाहिए।

आप टेबल पर ट्रिगर भी परिभाषित कर सकते हैं

CREATE TRIGGER trigger_name 
  BEFORE UPDATE ON TPM_INITIATIVES  
  FOR EACH ROW
DECLARE
BEGIN
  IF( :new.initiativeID != :old.initiativeID )
  THEN
    RAISE_APPLICATION_ERROR( -20001, 'Sorry Charlie.  You can''t update the initiativeID column' );
  END IF;
END;

कोई, निश्चित रूप से, ट्रिगर को अक्षम कर सकता है और अपडेट जारी कर सकता है। लेकिन मैं मान रहा हूं कि आप किसी हमलावर को रोकने की कोशिश नहीं कर रहे हैं, बस कोड का एक छोटा सा टुकड़ा है।

आप कौन से लक्षण देख रहे हैं, इसके विवरण के आधार पर, इस तालिका में कॉलम में परिवर्तनों के इतिहास को लॉग करना अधिक समझ में आता है ताकि आप अनुमान लगाने और छेद को प्लग करने का प्रयास करने के बजाय वास्तव में यह निर्धारित कर सकें कि क्या हो रहा है। -एक - एक करके। इसलिए, उदाहरण के लिए, आप ऐसा कुछ कर सकते हैं

CREATE TABLE TPM_INITIATIVES_HIST (
   INITIATIVEID    NUMBER NOT NULL,
   NAME            VARCHAR2(100) NOT NULL,
   ACTIVE          CHAR(1) NULL,
   SORTORDER       NUMBER NULL,
   SHORTNAME       VARCHAR2(100) NULL,
   PROJECTTYPEID   NUMBER NOT NULL,
   OPERATIONTYPE   VARCHAR2(1) NOT NULL,
   CHANGEUSERNAME  VARCHAR2(30),
   CHANGEDATE      DATE,
   COMMENT         VARCHAR2(4000)
);

CREATE TRIGGER trigger_name 
  BEFORE INSERT or UPDATE or DELETE ON TPM_INITIATIVES  
  FOR EACH ROW
DECLARE
  l_comment VARCHAR2(4000);
BEGIN
  IF( inserting )
  THEN
    INSERT INTO tpm_initiatives_hist( INITIATIVEID, NAME, ACTIVE, SORTORDER, SHORTNAME, PROJECTTYPEID, 
                                      OPERATIONTYPE, CHANGEUSERNAME, CHANGEDATE )
      VALUES( :new.initiativeID, :new.name, :new.active, :new.sortOrder, :new.shortName, :new.projectTypeID, 
              'I', USER, SYSDATE );
  ELSIF( inserting )
  THEN
    IF( :new.initiativeID != :old.initiativeID )
    THEN
      l_comment := 'Initiative ID changed from ' || :old.initiativeID || ' to ' || :new.initiativeID;
    END IF;
    INSERT INTO tpm_initiatives_hist( INITIATIVEID, NAME, ACTIVE, SORTORDER, SHORTNAME, PROJECTTYPEID, 
                                      OPERATIONTYPE, CHANGEUSERNAME, CHANGEDATE, COMMENT )
      VALUES( :new.initiativeID, :new.name, :new.active, :new.sortOrder, :new.shortName, :new.projectTypeID, 
              'U', USER, SYSDATE, l_comment );
  ELSIF( deleting )
  THEN
    INSERT INTO tpm_initiatives_hist( INITIATIVEID, NAME, ACTIVE, SORTORDER, SHORTNAME, PROJECTTYPEID, 
                                      OPERATIONTYPE, CHANGEUSERNAME, CHANGEDATE )
      VALUES( :old.initiativeID, :old.name, :old.active, :old.sortOrder, :old.shortName, :old.projectTypeID, 
              'D', USER, SYSDATE );
  END IF;
END;

फिर आप TPM_INITIATIVES_HIST query को क्वेरी कर सकते हैं समय के साथ किसी विशेष पंक्ति में किए गए सभी परिवर्तनों को देखने के लिए। तो आप देख सकते हैं कि प्राथमिक कुंजी मान बदल रहे हैं या कोई गैर-कुंजी फ़ील्ड बदल रहा है। आदर्श रूप से, आपके पास अतिरिक्त कॉलम हो सकते हैं जिन्हें आप परिवर्तनों को ट्रैक करने में सहायता के लिए इतिहास तालिका में जोड़ सकते हैं (यानी शायद V$SESSION से कुछ है। यह उपयोगी हो सकता है)।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. अनुक्रमणिका के बिना अद्वितीय बाधा

  2. ओरेकल 10+ में एनयूएलएल वाले कॉलम पर फ़ंक्शन-आधारित इंडेक्स का उपयोग कैसे करें?

  3. Oracle:TZNAME द्वारा पुनर्प्राप्त क्या यह संभव है?

  4. एक्सएमएल ओरेकल:मल्टीपल चाइल्ड नोड एक्सट्रैक्ट

  5. Oracle DB के लिए SQL क्वेरी में डेटटाइम पैरामीटर कैसे पास करें?