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

ORA-01779:एक कॉलम को संशोधित नहीं कर सकता जो एक गैर-कुंजी-संरक्षित तालिका में मैप करता है

एक डीएमएल टेबल एक्सप्रेशन क्लॉज केवल तभी उपयोगी होता है जब आपको एक से अधिक टेबल से कॉलम की आवश्यकता होती है। आपके मामले में, आप EXISTS . के साथ नियमित अपडेट का उपयोग कर सकते हैं :

update web_userrole
set role = replace(role, 'FULL', 'READ')
where read_only <> 'Y'
    and exists
    (
        select 1/0
        from web_userdatasource
        where datasource = p_datasource
            and username = web_userrole.username
    );

यदि आपको वास्तव में दोनों तालिकाओं के स्तंभों का उपयोग करने की आवश्यकता है तो आपके पास तीन विकल्प हैं:

  1. SET में शामिल होने को दोहराएं और WHERE खंड। इसे बनाना आसान है लेकिन इष्टतम नहीं है।
  2. डीएमएल तालिका अभिव्यक्ति। यह चाहिए काम करें, अगर आपके पास सही इंडेक्स हैं।
  3. MERGE , नीचे एक उदाहरण है।

    merge into web_userrole
    using
    (
        select distinct username
        from web_userdatasource
        where datasource = p_datasource
    ) web_userdatasource on
    (
        web_userrole.username = web_userdatasource.username
        and web_userrole.read_only <> 'Y'
    )
    when matched then update
    set role = replace(role, 'FULL', 'READ');
    

यह सीधे आपके प्रश्न का उत्तर नहीं देता है, बल्कि इसके बजाय कुछ कामकाज प्रदान करता है। मैं आपको जो त्रुटि प्राप्त कर रहा हूं उसे पुन:उत्पन्न नहीं कर सकता। मुझे इसे आगे देखने के लिए एक पूर्ण परीक्षण मामले की आवश्यकता होगी।

अद्यतन करने योग्य दृश्यों के लिए सामान्य सलाह

अद्यतन करने योग्य विचारों के साथ मुख्य समस्याओं में से एक उन प्रश्नों पर बड़ी संख्या में प्रतिबंध हैं जिनमें वे शामिल हो सकते हैं। क्वेरी या दृश्य में बहुत सारी विशेषताएं नहीं होनी चाहिए, जैसे कि DISTINCT, GROUP BY, कुछ अभिव्यक्ति, आदि। उन विशेषताओं वाली क्वेरी से अपवाद हो सकता है "ORA-01732:डेटा हेरफेर ऑपरेशन इस दृश्य पर कानूनी नहीं है"।

अद्यतन करने योग्य दृश्य क्वेरी को स्पष्ट रूप से संशोधित तालिका की प्रत्येक पंक्ति को केवल एक बार वापस करना चाहिए। क्वेरी "कुंजी संरक्षित" होनी चाहिए, जिसका अर्थ है कि ओरेकल प्राथमिक कुंजी या अद्वितीय बाधा का उपयोग करने में सक्षम होना चाहिए ताकि यह सुनिश्चित हो सके कि प्रत्येक पंक्ति केवल एक बार संशोधित हो।

यह प्रदर्शित करने के लिए कि कुंजी संरक्षित क्यों महत्वपूर्ण है, नीचे दिया गया कोड एक अस्पष्ट अद्यतन विवरण बनाता है। यह दो तालिकाएँ बनाता है, पहली तालिका में एक पंक्ति होती है और दूसरी तालिका में दो पंक्तियाँ होती हैं। तालिकाएँ A . कॉलम से जुड़ती हैं , और कॉलम को अपडेट करने का प्रयास करें B पहली तालिका में। इस मामले में यह अच्छा है कि Oracle अद्यतन को रोकता है, अन्यथा मान गैर-नियतात्मक होगा। कभी-कभी मान "1" पर सेट किया जाएगा, कभी-कभी इसे "2" पर सेट किया जाएगा।

--Create table to update, with one row.
create table test1 as
select 1 a, 1 b from dual;

--Create table to join two, with two rows that match the other table's one row.
create table test2 as
select 1 a, 1 b from dual union all
select 1 a, 2 b from dual;

--Simple view that joins the two tables.
create or replace view test_view as
select test1.a, test1.b b_1, test2.b b_2
from test1
join test2 on test1.a = test2.a;

--Note how there's one value of B_1, but two values for B_2.
select *
from test_view;

A  B_1  B_2
-  ---  ---
1    1    1
1    1    2

--If we try to update the view it fails with this error:
--ORA-01779: cannot modify a column which maps to a non key-preserved table
update test_view
set b_1 = b_2;

--Using a subquery also fails with the same error.
update
(
    select test1.a, test1.b b_1, test2.b b_2
    from test1
    join test2 on test1.a = test2.a
)
set b_1 = b_2;

MERGE बयान में समान प्रतिबंध नहीं हैं। MERGE कथन संकलन समय के बजाय रन टाइम पर अस्पष्टता का पता लगाने की कोशिश करता प्रतीत होता है।

दुर्भाग्य से MERGE हमेशा अस्पष्टता का पता लगाने का अच्छा काम नहीं करता है। Oracle 12.2 पर, नीचे दिया गया कथन कभी-कभी काम करेगा, और फिर विफल हो जाएगा। क्वेरी में छोटे-छोटे परिवर्तन करने से यह काम कर सकती है या विफल हो सकती है, लेकिन मुझे कोई विशिष्ट पैटर्न नहीं मिल रहा है।

--The equivalent MERGE may work and changes "2" rows, even though there's only one.
--But if you re-run, or uncomment out the "order by 2 desc" it might raise:
--  ORA-30926: unable to get a stable set of rows in the source tables
merge into test1
using
(
    select test1.a, test1.b b_1, test2.b b_2
    from test1
    join test2 on test1.a = test2.a
    --order by 2 desc
) new_rows
    on (test1.a = new_rows.a)
when matched then update set test1.b = new_rows.b_2;

UPDATE यदि डुप्लीकेट होना सैद्धांतिक रूप से संभव है तो संकलन समय पर विफल हो जाता है। कुछ कथन जो चाहिए काम नहीं चलेगा।

MERGE विफल रहता है अगर डेटाबेस रन टाइम पर अस्थिर पंक्तियों का पता लगाता है। कुछ कथन जो नहीं करने चाहिए काम अभी भी चलेगा।




  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 के TO_DATE में Java Date.toString

  2. ऑटो कमिट के साथ ऑरैकल टेबल बनाएं

  3. पतले ड्राइवर का उपयोग करके jdbc कनेक्शन

  4. जब बार-बार संसाधित किए जा सकने वाले आइटम के लिए ऑफ़सेट परिवर्तनशील होता है, तो मैं "अगला" ईवेंट कैसे प्राप्त करूं?

  5. Oracle DBMS_LOB के साथ समस्या का समाधान कैसे करें