2010-03-24 7 views
17

मेरे पास बहुत सारे टेबल और लाखों पंक्तियों के साथ बहुत बड़ा ओरेकल डेटाबेस है। मुझे उनमें से एक को हटाना होगा, लेकिन यह सुनिश्चित करना चाहते हैं कि इसे छोड़ना किसी भी अन्य निर्भर पंक्तियों को तोड़ नहीं देगा जो इसे एक विदेशी कुंजी रिकॉर्ड के रूप में इंगित करता है। क्या अन्य सभी रिकॉर्ड्स, या कम से कम टेबल स्कीमा की सूची प्राप्त करने का कोई तरीका है, जो इस पंक्ति को इंगित करता है? मुझे पता है कि मैं इसे खुद को हटाने की कोशिश कर सकता हूं, और अपवाद पकड़ सकता हूं, लेकिन मैं खुद स्क्रिप्ट नहीं चलाऊंगा और इसे पहली बार साफ करने के लिए इसकी आवश्यकता होगी।ओरेकल में एक रिकॉर्ड की ओर इशारा करते हुए विदेशी-कुंजी निर्भरताओं को कैसे ढूंढें?

मेरे पास ओरेकल से एसक्यूएल डेवलपर टूल्स हैं, और मेरे निपटान में ऑलराउंडऑटॉमेशंस से पीएल/एसक्यूएल डेवलपर हैं।

अग्रिम धन्यवाद!

+0

संदर्भित रिकॉर्ड फेंक अपवाद को हटाने का प्रयास नहीं करेगा? – Andrey

+0

@Andrey हाँ यह होगा, लेकिन मुझे इसे अपवाद फेंकने के बिना चलाने की आवश्यकता है। – daveslab

उत्तर

23

मैं हमेशा प्रारंभिक तालिका के लिए विदेशी कुंजी देखता हूं और अपना रास्ता वापस चलाता हूं। डीबी उपकरण आमतौर पर एक निर्भरता या बाधा नोड है। मैं जानता हूँ कि एल/SQL डेवलपर के लिए एक रास्ता FK के देखने के लिए है, लेकिन यह कुछ समय के बाद से मैं इसे इस्तेमाल किया है किया गया है, तो मैं यह व्याख्या नहीं कर सकते ...

सिर्फ एक तालिका नाम के साथ XXXXXXXXXXXX की जगह ...

/* The following query lists all relationships */ 

select 
a.owner||'.'||a.table_name "Referenced Table" 
,b.owner||'.'||b.table_name "Referenced by" 
,b.constraint_name "Foreign Key" 
from all_constraints a, all_constraints b 
where 
b.constraint_type = 'R' 
and a.constraint_name = b.r_constraint_name 
and b.table_name='XXXXXXXXXXXX' -- Table name 
order by a.owner||'.'||a.table_name 
+1

एसक्यूएल केस संवेदनशील – eschneider

+0

क्या आप उस क्वेरी को 'कोड' मोड में डाल सकते हैं, तो इसे पढ़ने में थोड़ा आसान है? अन्यथा, मैं अब कोशिश कर रहा हूँ। – daveslab

+0

एसक्यूएल के साथ अपनी प्रतिक्रिया का हिस्सा चुनें और फिर दबाएं या उद्धरण चिह्न के साथ संपादक टूलबार में सीधे दाएं बटन दबाएं। इसे कई लाइनों पर भी तोड़ना सुनिश्चित करें। – daveslab

3

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

SQL> declare 
    2  n pls_integer; 
    3  tot pls_integer := 0; 
    4 begin 
    5  for lrec in (select table_name from user_constraints 
    6     where r_constraint_name = 'T23_PK') 
    7  loop 
    8   execute immediate 'select count(*) from '||lrec.table_name 
    9        ||' where col2 = :1' into n using &&target_val; 
10   if n = 0 then 
11    dbms_output.put_line('No impact on '||lrec.table_name); 
12   else 
13    dbms_output.put_line('Uh oh! '||lrec.table_name||' has '||n||' hits!'); 
14   end if; 
15   tot := tot + n; 
16  end loop; 
17  if tot = 0 
18  then 
19   delete from t23 where col2 = &&target_val; 
20   dbms_output.put_line('row deleted!'); 
21  else 
22   dbms_output.put_line('delete aborted!'); 
23  end if; 
24 end; 
25/
Enter value for target_val: 6 
No impact on T34 
Uh oh! T42 has 2 hits! 
No impact on T69 
delete aborted! 

PL/SQL procedure successfully completed. 

SQL> 

यह उदाहरण एक सा धोखा देती है। लक्ष्य प्राथमिक कुंजी का नाम हार्डकोड किया गया है, और रेफरेंसिंग कॉलम का सभी आश्रित सारणी पर समान नाम है। इन मुद्दों का निपटान पाठक के लिए एक व्यायाम के रूप में छोड़ दिया जाता है;)

23

यहाँ एक मेज के सभी संदर्भ सूची मेरा समाधान है:

select 
    src_cc.owner as src_owner, 
    src_cc.table_name as src_table, 
    src_cc.column_name as src_column, 
    dest_cc.owner as dest_owner, 
    dest_cc.table_name as dest_table, 
    dest_cc.column_name as dest_column, 
    c.constraint_name 
from 
    all_constraints c 
inner join all_cons_columns dest_cc on 
    c.r_constraint_name = dest_cc.constraint_name 
    and c.r_owner = dest_cc.owner 
inner join all_cons_columns src_cc on 
    c.constraint_name = src_cc.constraint_name 
    and c.owner = src_cc.owner 
where 
    c.constraint_type = 'R' 
    and dest_cc.owner = 'MY_TARGET_SCHEMA' 
    and dest_cc.table_name = 'MY_TARGET_TABLE' 
    --and dest_cc.column_name = 'MY_OPTIONNAL_TARGET_COLUMN' 
; 

इस समाधान आप भी जो स्तंभ जो तालिका के की जानकारी के साथ आपकी लक्षित तालिका के कौन से कॉलम का संदर्भ दे रहा है (और आप इसे फ़िल्टर कर सकते हैं)।

5

मुझे हाल ही में एक ही समस्या थी, लेकिन जल्द ही अनुभव किया गया कि प्रत्यक्ष निर्भरता ढूंढना पर्याप्त नहीं है। इसलिए मैं बहुस्तरीय विदेशी कुंजी निर्भरता का एक वृक्ष को दिखाने के लिए एक प्रश्न लिखा है:

SELECT LPAD(' ',4*(LEVEL-1)) || table1 || ' <-- ' || table2 tables, table2_fkey 
FROM 
    (SELECT a.table_name table1, b.table_name table2, b.constraint_name table2_fkey 
    FROM user_constraints a, user_constraints b 
    WHERE a.constraint_type IN('P', 'U') 
    AND b.constraint_type = 'R' 
    AND a.constraint_name = b.r_constraint_name 
    AND a.table_name != b.table_name 
    AND b.table_name <> 'MYTABLE') 
CONNECT BY PRIOR table2 = table1 AND LEVEL <= 5 
START WITH table1 = 'MYTABLE'; 

यह इस तरह एक परिणाम देता है, जब मेरे डेटाबेस में mytable के रूप में शिपमेंट का उपयोग कर:

SHIPMENT <-- ADDRESS 
SHIPMENT <-- PACKING_LIST 
    PACKING_LIST <-- PACKING_LIST_DETAILS 
    PACKING_LIST <-- PACKING_UNIT 
     PACKING_UNIT <-- PACKING_LIST_ITEM 
    PACKING_LIST <-- PO_PACKING_LIST 
... 
0

मैं कैसे आश्चर्यचकित था विदेशी कुंजी संबंधों के आधार पर तालिकाओं के निर्भरता आदेश को ढूंढना मुश्किल था। मुझे इसकी आवश्यकता थी क्योंकि मैं सभी तालिकाओं से डेटा हटाना चाहता था और इसे फिर से आयात करना चाहता था। निर्भरता क्रम में तालिकाओं को सूचीबद्ध करने के लिए मैंने लिखा प्रश्न यहां दिया गया है। मैं नीचे दी गई क्वेरी का उपयोग करके हटाए गए लिपियों को स्क्रिप्ट करने में सक्षम था, और क्वेरी के परिणामों का उपयोग रिवर्स ऑर्डर में कर रहा था।

SELECT referenced_table 
     ,MAX(lvl) for_deleting 
     ,MIN(lvl) for_inserting 
    FROM 
     (-- Hierarchy of dependencies 
     SELECT LEVEL lvl 
       ,t.table_name referenced_table 
       ,b.table_name referenced_by 
     FROM user_constraints A 
     JOIN user_constraints b 
       ON A.constraint_name = b.r_constraint_name 
       and b.constraint_type = 'R' 
     RIGHT JOIN user_tables t 
       ON t.table_name = A.table_name 
     START WITH b.table_name IS NULL 
     CONNECT BY b.table_name = PRIOR t.table_name 
     ) 
    GROUP BY referenced_table 
    ORDER BY for_deleting, for_inserting; 
0

ओरेकल बाधा डेटा संदर्भ के लिए तालिका इंडेक्स का उपयोग करती है।
यह पता लगाने के लिए कि कौन सी तालिका एक तालिका का संदर्भ दे रही है, बस सूचकांक को रिवर्स ऑर्डर में देखें।

/* Toggle ENABLED and DISABLE status for any referencing constraint: */ 

select 'ALTER TABLE '||b.owner||'.'||b.table_name||' '|| 
     decode(b.status, 'ENABLED', 'DISABLE ', 'ENABLE ')|| 
     'CONSTRAINT '||b.constraint_name||';' 
    from all_indexes a, 
     all_constraints b 
where a.table_name='XXXXXXXXXXXX' -- Table name 
    and a.index_name = b.r_constraint_name; 

Obs .: अक्षम करना संदर्भ में काफी बेहतर बनाता है DML के समय आदेश (अपडेट करें, हटाएं और सम्मिलित)।

यह थोक संचालन में बहुत मदद कर सकता है, जहां आप जानते हैं कि सभी डेटा सुसंगत है।

/* List which columns are referenced in each constraint */ 

select ' TABLE "'||b.owner||'.'||b.table_name||'"'|| 
     '('||listagg (c.column_name, ',') within group (order by c.column_name)||')'|| 
     ' FK "'||b.constraint_name||'" -> '||a.table_name|| 
     ' INDEX "'||a.index_name||'"' 
     "REFERENCES" 
    from all_indexes a, 
     all_constraints b, 
     all_cons_columns c 
where rtrim(a.table_name) like 'XXXXXXXXXXXX' -- Table name 
    and a.index_name = b.r_constraint_name 
    and c.constraint_name = b.constraint_name 
group by b.owner, b.table_name, b.constraint_name, a.table_name, a.index_name 
order by 1; 
संबंधित मुद्दे

 संबंधित मुद्दे