Zatímco byste to mohli udělat...
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
... výkon pomocí dynamického SQL bude obvykle lepší , protože vygeneruje cílenější plán dotazů. Ve výše uvedeném dotazu Oracle nedokáže říct, zda použít index pro bcode nebo lb nebo typ nebo edate, a pravděpodobně pokaždé provede úplné prohledání tabulky.
Samozřejmě, že musíte použijte v dynamickém dotazu proměnné vazby, nezřetězujte doslovné hodnoty do řetězce, jinak bude výkon (a škálovatelnost a zabezpečení) velmi špatný .
Aby bylo jasno, dynamická verze, kterou mám na mysli, by fungovala takto:
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;
To znamená, že dotaz na výsledek bude být "sargable" (pro mě nové slovo musím přiznat!), protože výsledný běh dotazu bude (například):
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
Souhlasím však s tím, že by to v tomto příkladu mohlo vyžadovat až 16 tvrdých analýz. Klauzule "and :bv is null" jsou vyžadovány při použití nativního dynamického SQL, ale lze se jim vyhnout použitím DBMS_SQL.
Poznámka:použití (1=1 or :bindvar is null)
když je proměnná bind null navrhl v komentáři Michal Pravda, protože umožňuje optimalizátoru klauzuli eliminovat.