Chociaż możesz to zrobić...
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
... wydajność przy użyciu dynamicznego SQL będzie zwykle lepsza , ponieważ wygeneruje bardziej ukierunkowany plan zapytań. W powyższym zapytaniu Oracle nie może powiedzieć, czy użyć indeksu w kodzie bcode lub lb, czy też wpisać lub edate i prawdopodobnie za każdym razem wykona pełne skanowanie tabeli.
Oczywiście musisz używaj zmiennych wiązania w zapytaniu dynamicznym, nie łącz wartości literałów w ciągu, w przeciwnym razie wydajność (oraz skalowalność i bezpieczeństwo) będą bardzo złe .
Żeby było jasne, dynamiczna wersja, którą mam na myśli, działałaby tak:
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;
Oznacza to, że zapytanie wynikowe będzie być "sargable" (dla mnie nowe słowo, muszę przyznać!), ponieważ wynikowe zapytanie będzie (na przykład):
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
Zgadzam się jednak, że w tym przykładzie może to wymagać do 16 twardych analiz. Klauzule "and :bv is null" są wymagane podczas używania natywnego dynamicznego SQL, ale można ich uniknąć używając DBMS_SQL.
Uwaga:użycie (1=1 or :bindvar is null)
gdy zmienna bind ma wartość null, została zasugerowana w komentarzu przez Michala Pravdę, ponieważ pozwala to optymalizatorowi wyeliminować klauzulę.