Mentre potresti farlo...
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
... le prestazioni utilizzando l'SQL dinamico saranno generalmente migliori , poiché genererà un piano di query più mirato. Nella query precedente, Oracle non è in grado di dire se utilizzare un indice su bcode o lb o type o edate e probabilmente eseguirà una scansione completa della tabella ogni volta.
Naturalmente, devi usa le variabili bind nella tua query dinamica, non concatena i valori letterali nella stringa, altrimenti le prestazioni (e la scalabilità e la sicurezza) saranno pessime .
Per essere chiari, la versione dinamica che ho in mente funzionerebbe in questo modo:
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;
Ciò significa che la query del risultato sarà essere "sargable" (una nuova parola per me devo ammettere!) poiché l'esecuzione della query risultante sarà (ad esempio):
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
Tuttavia, accetto che ciò potrebbe richiedere fino a 16 analisi hard in questo esempio. Le clausole "and :bv is null" sono richieste quando si utilizza l'SQL dinamico nativo, ma possono essere evitate utilizzando DBMS_SQL.
Nota:l'uso di (1=1 or :bindvar is null)
quando la variabile bind è nulla è stato suggerito in un commento da Michal Pravda, in quanto consente all'ottimizzatore di eliminare la clausola.