Även om du kunde göra det här...
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
... prestanda med dynamisk SQL kommer vanligtvis att vara bättre , eftersom det kommer att generera en mer riktad frågeplan. I ovanstående fråga kan Oracle inte säga om man ska använda ett index på bcode eller lb eller typ eller edate, och kommer förmodligen att utföra en fullständig tabellsökning varje gång.
Självklart måste du använd bindningsvariabler i din dynamiska fråga, inte sammanfoga de bokstavliga värdena i strängen, annars blir prestanda (och skalbarhet och säkerhet) mycket dålig .
För att vara tydlig skulle den dynamiska versionen jag har i åtanke fungera så här:
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;
Det betyder att resultatfrågan kommer vara "sargable" (ett nytt ord för mig måste jag erkänna!) eftersom den resulterande frågekörningen blir (till exempel):
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
Jag accepterar dock att detta kan kräva upp till 16 hårda analyser i detta exempel. "och :bv är null"-satser krävs när du använder inbyggd dynamisk SQL, men kan undvikas genom att använda DBMS_SQL.
Obs:användningen av (1=1 or :bindvar is null)
när bindningsvariabeln är null föreslogs i en kommentar av Michal Pravda, eftersom den tillåter optimeraren att eliminera klausulen.