查询中的PL / SQL空值问题

时间:2011-07-07 07:18:27

标签: sql oracle function plsql

我必须创建一个pl / sql函数,它接受七个输入参数。

问题是用户可以以任何组合传递任何这些参数,使得剩余参数为空。因此,许多组合是可能的。我必须在删除空参数后使用这些参数查询表。

有没有办法在不使用嵌套ifs数来检查空值的情况下执行此操作?

4 个答案:

答案 0 :(得分:3)

在WHERE子句

中,检查输入参数是否为null

例如,假设输入参数是parameter1,parameter2,parameter3

select * from tableA
where (col1 = parameter1 or parameter1  is null)
and (col2 = parameter2 or parameter2  is null)
and (col3 = parameter3 or parameter3  is null)

如果parameter1为null,则对于此参数的条件,它将始终返回true。

答案 1 :(得分:2)

1解决方案是在where子句中使用逻辑来短路条件

e.g:

SELECT blah WHERE (param1 IS NOT NULL AND col1=param1)
     OR (param2 IS NOT NULL AND col2=param2) ….etc

注意:没有参数=没有结果

    SELECT blah WHERE (param1 IS NULL OR col1=param1)
     AND (param2 IS NULL OR col2=param2) ….etc

注意:没有参数=所有结果

答案 2 :(得分:2)

您可以使用

select * from table t where 
(param1 is null or t.column1 = param1) and 
(param2 ....)

但这会 NOT 使用表格中的任何索引,或者在最坏的情况下,使用不合适的索引(由于光标共享,在11G之前无法避免。在11G中它有时可能有效但这不是你应该依赖的东西。)

要获得更好的解决方案,您必须使用动态查询。在PLSQL中,这是在大多数情况下使用execute immediate l_query; (or open cursor for l_query;)完成的,或者通过更强大的(但使用起来要复杂得多)DBMS_SQL(在非常有限的出现次数中需要)来完成。

更简单(但使用文字因此几乎在运行时需要进行硬解析)解决方案

procedure dynamic_query_literals (param1 ... param7)
is
  l_query varchar2(1000);
  l_cursor sys_refcursor;
begin
  l_query := 'select * from table t where 1=1';
if (param1 is not null) then 
  l_query := l_query || ' and t.column1 = param1';
end if;
if (param2 ...)
  open l_cursor for l_query;

  -- do whatever needed with the result set in the cursor. 
  --The procedure can even return this cursor...
end;

更复杂但性能更高(特别是如果这个过程被多次调用)解决方案需要绑定参数(当你在plsql中使用静态sql时,它会自动透明地完成)

procedure dynamic_query_binding (param1 ... param7)
is
  l_query varchar2(1000);
  l_cursor sys_refcursor;
begin
  l_query := 'select * from table t where 1=1';

if (param1 is null) then 
  --this will get optimised away in the process but is required 
  --syntactically for use of "using" later
  l_query := l_query || ' and 1=1 or :param1 is null';
else
  l_query := l_query || ' and t.column1 = :param1';
end if;

if (param2 ...)

open l_cursor for l_query
using param1, param2, ... param7;

  -- do whatever needed with the result set in the cursor. 
  -- The procedure can even return this cursor...
end;

此版本将根据需要使用表格中的索引,并且每个参数的“无效”组合仍然只能获得一次硬分析。

这两个动态版本的缺点是你没有得到编译时语法检查。

答案 3 :(得分:0)

您可以使用以下内容:

select * from tableA
where col1 = nvl(parameter1, col1) 
and ....