我有一个工作场所问题,我正在寻找一个简单的解决方案。 我想在较小的场景中复制它。在Oracle 11g中使用NVL和IN子句的替代方案
问题在短期
我想用nvl
的in
子句中。目前我有一个由名字组成的输入字符串。它被用在如下的where子句中
and column_n = nvl(in_parameter,column_n)
现在我想在同一输入参数中传递多个逗号分隔值。所以如果我用=
替换in
,并将输入逗号分隔的字符串转置为行,我就不能使用nvl
子句。
问题详情
让我们考虑一个Employee表EMP1。
Emp1
+-------+-------+
| empno | ename |
+-------+-------+
| 7839 | KING |
| 7698 | BLAKE |
| 7782 | CLARK |
+-------+-------+
现在,这是一个现有的存储过程
create or replace procedure emp_poc(in_names IN varchar2)
as
cnt integer;
begin
select count(*)
into cnt
from emp1
where
ename = nvl(in_names,ename); --This is one of the condition where we will make the change.
dbms_output.put_line(cnt);
end;
因此,这将给作为输入参数传递的雇员数的计数的简单版本。但是,如果我们传递null,它将返回nvl
的员工的全部计数。
因此,这些过程调用将渲染给定的输出。
Procedure Call Output
exec emp_poc('KING') 1
exec emp_poc('JOHN') 0
exec emp_poc(null) 3
现在我想实现的是添加另一个功能。所以exec emp_poc('KING,BLAKE')
应该给我2
。所以我想出了一种将逗号分隔的字符串拆分为行并在过程中使用它的方法。
所以,如果我改变where
条款如下,以in
create or replace procedure emp_poc2(in_names IN varchar2)
as
cnt integer;
begin
select count(*)
into cnt
from emp1
where
ename in (select trim(regexp_substr(in_names, '[^,]+', 1, level))
from dual
connect by instr(in_names, ',', 1, level - 1) > 0
);
dbms_output.put_line(cnt);
end;
所以exec emp_poc2('KING','BLAKE')
给我2
。但通过null
将得到结果为0
。不过,我想要3
像emp_proc
这样的情况我不能使用nvl
和in
,因为它期望子查询返回单个值。
我能想到的一种方法是在基于输入参数的变量中重建整个查询,然后使用execute immediate
。但我正在使用一些变量来收集价值,并且很难通过execute immediate
来实现。
我再次强调这是一个复杂过程的简单版本,我们捕获许多变量并且它加入很多表并且在where子句中有多个AND
条件。
关于如何使这项工作的任何想法。
它是强制性的输入变量('in_names')数据类型是一个字符串,或者可以它是一个集合/容器数据类型而不是? – user272735
这不是强制性的。无论哪个更好,我都可以使用它。 – Utsav
逗号分隔的列表在SQL或PL/SQL中并不像其他语言中的那样 - 它只是一个恰好包含逗号的文本字符串。没有内建的方式将其视为文字列表或一系列元素或其他任何东西。 –