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

पीएल/एसक्यूएल - कहां-क्लॉज में वैकल्पिक स्थितियां - गतिशील एसक्यूएल के बिना?

जबकि आप ऐसा कर सकते थे...

select num
from (select distinct q.num
       from cqqv q
       where 1=1
             and (:bcode is null or q.bcode = :bcode)
             and (:lb is null or q.lb = :lb)
             and (:type is null or q.type = :type)
             and (:edate is null or q.edate > :edate - 30)
       order by dbms_random.value()) subq
where rownum <= :numrows

... डायनेमिक SQL का उपयोग करने वाला प्रदर्शन आमतौर पर बेहतर होगा , क्योंकि यह अधिक लक्षित क्वेरी योजना उत्पन्न करेगा। उपरोक्त क्वेरी में, Oracle यह नहीं बता सकता है कि bcode या lb पर किसी अनुक्रमणिका का उपयोग करना है या टाइप या संपादित करना है, और संभवतः हर बार एक पूर्ण तालिका स्कैन करेगा।

बेशक, आपको जरूरी अपनी डायनामिक क्वेरी में बाइंड वेरिएबल्स का उपयोग करें, शाब्दिक मानों को स्ट्रिंग में संयोजित न करें, अन्यथा प्रदर्शन (और मापनीयता, और सुरक्षा) बहुत खराब होगा ।

स्पष्ट होने के लिए, मेरे मन में जो गतिशील संस्करण है वह इस तरह काम करेगा:

declare
    rc sys_refcursor;
    q long;
begin
    q := 'select num
    from (select distinct q.num
           from cqqv q
           where 1=1';

    if p_bcode is not null then
        q := q || 'and q.bcode = :bcode';
    else
        q := q || 'and (1=1 or :bcode is null)';
    end if;

    if p_lb is not null then
        q := q || 'and q.lb = :lb';
    else
        q := q || 'and (1=1 or :lb is null)';
    end if;

    if p_type is not null then
        q := q || 'and q.type = :type';
    else
        q := q || 'and (1=1 or :type is null)';
    end if;

    if p_edate is not null then
        q := q || 'and q.edate = :edate';
    else
        q := q || 'and (1=1 or :edate is null)';
    end if;

    q := q || ' order by dbms_random.value()) subq
    where rownum <= :numrows';

    open rc for q using p_bcode, p_lb, p_type, p_edate, p_numrows;
    return rc;
end;

इसका अर्थ है कि परिणाम क्वेरी होगी हो "सरगेबल" (मेरे लिए एक नया शब्द मुझे स्वीकार करना चाहिए!) क्योंकि परिणामी क्वेरी रन होगा (उदाहरण के लिए):

select num
from (select distinct q.num
       from cqqv q
       where 1=1
             and q.bcode = :bcode
             and q.lb = :lb
             and (1=1 or :type is null)
             and (1=1 or :edate is null)
       order by dbms_random.value()) subq
where rownum <= :numrows

हालांकि, मैं स्वीकार करता हूं कि इस उदाहरण में इसके लिए 16 हार्ड पार्स की आवश्यकता हो सकती है। देशी डायनेमिक SQL का उपयोग करते समय "और :bv is null" क्लॉज़ की आवश्यकता होती है, लेकिन DBMS_SQL का उपयोग करके इसे टाला जा सकता है।

नोट:(1=1 or :bindvar is null) . का उपयोग जब बाइंड वेरिएबल शून्य है, तो मीकल प्रावदा द्वारा एक टिप्पणी में सुझाव दिया गया था, क्योंकि यह ऑप्टिमाइज़र को क्लॉज को खत्म करने की अनुमति देता है।



  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 क्वेरी:अल्पविराम से अलग किए गए मान वाले विभिन्न तालिका के दो स्तंभों की तुलना कैसे करें?

  2. ऑरैकल में मर्ज स्टेटमेंट के साथ ट्रिगर

  3. सबक्वेरी फैक्टरिंग के साथ Oracle DELETE स्टेटमेंट

  4. SQL डेवलपर में डेटा आयात करते समय टाइमस्टैम्प पढ़ना

  5. JPA + StoredProcedureCall + ऑब्जेक्ट प्रकार IN पैरामीटर