Докато можете да направите това...
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 или type или edate и вероятно ще извършва пълно сканиране на таблица всеки път.
Разбира се, четрябва използвайте свързващи променливи във вашата динамична заявка, а не свързвайте литералните стойности в низа, в противен случай производителността (и скалируемостта, и сигурността) ще бъдат много лоши .
За да бъде ясно, динамичната версия, която имам предвид, ще работи по следния начин:
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;
Това означава, че заявката за резултатще бъде "sargable" (нова дума за мен, трябва да призная!), тъй като получената заявка ще бъде (например):
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 твърди анализа в този пример. Клаузите "and :bv is null" са задължителни при използване на естествен динамичен SQL, но могат да бъдат избегнати чрез използване на DBMS_SQL.
Забележка:използването на (1=1 or :bindvar is null)
когато променливата за свързване е нула, беше предложено в коментар от Михал Правда, тъй като позволява на оптимизатора да елиминира клаузата.