2009-07-06 10 views
10

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

यहाँ मेरी सर्वश्रेष्ठ अनुमान दिया है, और जब तक इसे बाहर बारी मेरी प्रयोजनों के लिए काफी तेजी से हो सकता है, मैं एक विहित रास्ता मूल रूप से एसक्यूएल सर्वर के ऐसा करने के लिए सीखने के लिए अच्छा लगेगा "मौजूद है" Oracle में:

select count(x_id) from x where x.col_a = value_a and x.col_b = value_b; 

गिनती() को एक और स्तर में एक बूलियन के रूप में वापस कर दिया जाएगा। मुख्य बिंदु यह है कि मैं ओरेकल को इस प्रश्न के लिए न्यूनतम न्यूनतम करना चाहता हूं - मुझे केवल यह जानने की जरूरत है कि मानदंडों से मेल खाने वाली कोई पंक्तियां हैं या नहीं।

और हाँ, उन कॉलम को निश्चित रूप से अनुक्रमित किया जाएगा।

उत्तर

16

COUNT का उपयोग करना (*) ठीक है अगर आप भी उपयोग ROWNUM = 1:

declare 
    l_cnt integer; 
begin 
    select count(*) 
    into l_cnt 
    from x 
    where x.col_a = value_a 
    and x.col_b = value_b 
    and rownum = 1; 
end; 

यह हमेशा एक पंक्ति को संभालने के लिए तो कोई ज़रूरत नहीं वापस आ जाएगी, कोई NO_DATA_FOUND अपवाद। L_cnt का मान 0 (कोई पंक्ति नहीं) या 1 (कम से कम 1 पंक्ति मौजूद है)।

+1

@ टोनी जैसे IF EXISTS का उपयोग नहीं कर सकते - क्या आप EXISTS के बजाय गिनती (*) करेंगे? मेरे लिए, यदि आप अपवाद से निपटने की ज़रूरत है तो भी एक EXISTS अधिक प्राकृतिक लगता है। –

+0

क्या आपका मतलब है "जहां मौजूद दोहरी से 1 का चयन (...)"? मैं नहीं करूँगा, लेकिन समझ सकता हूं कि कुछ क्यों करेंगे। वास्तव में वास्तव में प्राकृतिक होना चाहता है एक पीएल/एसक्यूएल निर्माण है जैसे "अगर मौजूद है (चुनें ...) तो ..."! –

+0

मैं इसे अपने आप परीक्षण नहीं द्वारा यहाँ आलसी जा रहा हूँ, लेकिन गिनती नहीं होगा (x_id) की तुलना में गिनती (*) तेज हो सकता है, या एसक्यूएल दुभाषिया बहुत चालाक देखने के लिए कि यह वास्तव में विस्तार करने के लिए की जरूरत नहीं है कि "*" ? –

5
SELECT NULL 
FROM x 
WHERE x.col_a = value_a 
     AND x.col_b = value_b 
     AND rownum = 1 

COUNT(*) नहीं निश्चित रूप से सबसे अच्छा तरीका है, क्योंकि यह सभी पंक्तियों गिनती करने की आवश्यकता होगी, के रूप में यह पहली मिलान पंक्ति पाता है, जबकि ROWNUM = 1 रिटर्न जैसे ही।

यहाँ PL/SQL कोड है:

DECLARE 
     ex INT; 
BEGIN 
     BEGIN 
       SELECT NULL 
       INTO ex 
       FROM dual 
       WHERE 1 = 1 
         AND rownum = 1; 
       DBMS_OUTPUT.put_line('found'); 
     EXCEPTION 
     WHEN no_data_found THEN 
       DBMS_OUTPUT.put_line('not found'); 
     END; 
END; 
+0

शायद यहां तक ​​कि एक FIRST_ROWS संकेत भी हो सकता है? जब मुझे लगता है कि rownum = 1 मुझे लगता है तो अनुकूलक को यह स्पष्ट रूप से करना चाहिए। SELECT/* + FIRST_ROWS (n) */NULL –

+0

@Robert: बेशक यह एक को जोड़ने में कोई दिक्कत नहीं होगी, लेकिन यह वास्तव में केवल जुड़ने में काम करता है (यह ऑप्टिमाइज़र को नेस्टेड लूप को हश जॉइन के ऊपर पसंद करने के लिए बनाता है) – Quassnoi

+1

@ Quassnoi: मैंने सोचा था कि यह अनुकूलक 'इंडेक्स खुश' भी बनाता है। –

1
begin 
select 'row DOES exist' 
    into ls_result 
from dual 
where exists (select null from x where x.col_a = value_a and x.col_b = value_b); 
exception 
when no_data_found then 
    ls_result := ' row does NOT exist'; 
end; 
7

मुझे लगता है कि EXISTS का उपयोग करके ROWNUM का उपयोग करके COUNT क्वेरी को अनुकूलित करने का प्रयास करने से प्रश्न का अधिक प्राकृतिक उत्तर मिलता है।

ओरेकल आपके लिए ROWNUM ऑप्टिमाइज़ेशन करने दें।

create or replace function is_exists (
     p_value_a varchar2, 
     p_value_b varchar2) 
     return boolean 
is 

    v_exists varchar2(1 char); 

begin 

    begin 
     select 'Y' into v_exists from dual 
     where exists 
      (select 1 from x where x.col_a = p_value_a and x.col_b = p_value_a); 

    exception 

     when no_data_found then 

      v_exists := null; 

    end; 

    return v_exists is not null; 

end is_exists; 
संबंधित मुद्दे