Лучший способ обработки различных перестановок входных переменных состоит в том, чтобы динамически собирать запрос. В следующем примере будет выполняться запрос, который хорошо работает и обрабатывает значения NULL аккуратно, чтобы вернуть правильный результат.
create or replace function get_dyn_emps
(i_empno in emp.empno%type
, i_ename in emp.ename%type
, i_deptno in emp.deptno%type)
return sys_refcursor
is
rc sys_refcursor;
stmt varchar2(32767);
begin
stmt := 'select * from emp where 1=1';
if i_empno is not null
then
stmt := stmt||' and empno = :p_empno';
else
stmt := stmt||' and (1=1 or :p_empno is null)';
end if;
if i_ename is not null
then
stmt := stmt||' and ename = :p_ename';
else
stmt := stmt||' and (1=1 or :p_ename is null)';
end if;
if i_deptno is not null
then
stmt := stmt||' and deptno = :p_deptno';
else
stmt := stmt||' and (1=1 or :p_deptno is null)';
end if;
open rc for stmt
using i_empno, i_ename , i_deptno;
return rc;
end get_dyn_emps;
/
Это может показаться, как многословно решением по сравнению с текущим общепринятым ответом, но вот почему это лучший подход: возвращает правильный ответ.
В deparment 40 есть сотрудник без имени:
SQL> var rc refcursor
SQL> exec :rc := get_dyn_emps(null, null, 40)
PL/SQL procedure successfully completed.
SQL> print rc
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
------- ---------- --------- ---------- --------- ---------- ---------- ---------
8101 03-DEC-10 40
SQL>
Если я реализовать, по-видимому аккуратнее DECODE решение() ...
create or replace function get_fix_emps
(i_empno in emp.empno%type
, i_ename in emp.ename%type
, i_deptno in emp.deptno%type)
return sys_refcursor
is
rc sys_refcursor;
begin
open rc for
SELECT * FROM emp
WHERE empno = DECODE(NVL(i_empno,0), 0, empno, i_empno)
AND ename = DECODE(NVL(i_ename,'X'), 'X', ename, i_ename)
AND deptno = DECODE(NVL(i_deptno,0), 0, deptno, i_deptno);
return rc;
end get_fix_emps;
/
... это то, что происходит:
SQL> exec :rc := get_fix_emps(null, null, 40)
PL/SQL procedure successfully completed.
SQL> print rc
no rows selected
SQL>
Поскольку NULL не когда-либо равное NULL, что и ename = DECODE(NVL(i_ename,'X'), 'X', ename, i_ename)
имеет значение в этом случае.
Вы можете получить проблемы с производительностью, так как запрос не может легко использовать индексы с такой конструкцией. Иногда IF..ELSIF ... ELSE..END IF; является лучшим вариантом – 2010-12-02 08:34:21
Yeh Я знаю, но этот подход я использовал в основном с Oracle Reports, где я должен основывать отчет по определенным критериям. – asifabbas 2010-12-02 08:59:27