我需要创建一个Oracle查询,例如
select * from emp where emp_id=i_emp_id and emp_nm=i_emp_nm and emp_dpt=i_emp_dpt
如果所有三个输入都不为空,它应该像
一样运行select * from emp where emp_id=i_emp_id and emp_nm=i_emp_nm and emp_dpt=i_emp_dpt
如果我将i_emp_id传递为null,则查询应该像
一样运行select * from emp where emp_nm=i_emp_nm and emp_dpt=i_emp_dpt
如果我将i_emp_id传递为null并将i_emp_dpt传递为null,则查询应该像
一样运行select * from emp where emp_nm=i_emp_nm
答案 0 :(得分:1)
处理输入变量的不同排列的最佳方法是动态组合查询。以下示例将生成一个执行良好并且整齐地处理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;
/
与目前接受的答案相比,这似乎是一个冗长的解决方案,但这就是为什么它是更好的方法:它返回正确答案。
在公证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)
在这种情况下评估的内容。
答案 1 :(得分:0)
正如我在我的应用程序中所做的那样,您只需使用NVL和DECODE函数即可实现此功能。
SELECT * FROM emp
WHERE emp_id = DECODE(NVL(i_emp_id,0), 0, emp_id, i_emp_id)
AND emp_nm = DECODE(NVL(i_emp_nm,0), 0, emp_nm, i_emp_nm)
AND emp_dpt = DECODE(NVL(i_emp_dpt,'X'), 'X', emp_dpt, i_emp_dpt)
如果i_emp_id
为空,则它将与当前值匹配,因此所有记录都将匹配,否则仅记录匹配i_emp_id
的记录将返回。同样适用于emp_nm
和emp_dpt
。