जबकि आप ऐसा कर सकते थे...
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)
. का उपयोग जब बाइंड वेरिएबल शून्य है, तो मीकल प्रावदा द्वारा एक टिप्पणी में सुझाव दिया गया था, क्योंकि यह ऑप्टिमाइज़र को क्लॉज को खत्म करने की अनुमति देता है।