根据用户参数输入循环

时间:2012-10-31 12:33:40

标签: sql database oracle plsql plsqldeveloper

有4个参数.material,Suppliernbr,Suppliername,Materail代码。我的查询是用户是否在一个参数中输入任何一个参数,我需要输入循环。

For Eg:
P_suppname='stack'
p_matrl='NULL'
p_suppnbr:=NULL
P_mtrlcde='NULL' I can go inside 

但是如果

P_suppname=NULL
p_matrl=211
p_suppnbr:=43443443
P_mtrlcde='NULL' I shouldnt go.

另外

P_suppname=NULL
p_matrl='211;2322'
p_suppnbr:=NULL
P_mtrlcde='NULL' I should nt go

怎么做?

3 个答案:

答案 0 :(得分:0)

计算每个参数中;的数量,使用nvl在空值上计算零:

select 
  nvl( length('211;2322')    - length(replace('211;2322', ';', ''))    +1, 0), -->2
  nvl( length('211;2322;34') - length(replace('211;2322;34', ';', '')) +1, 0), -->3
  nvl( length(Null)          - length(replace(Null, ';', ''))          +1, 0)  -->0
from dual

IF条件下使用:

IF ( nvl( length(p_suppname) - length(replace(p_suppname, ';', '')) +1, 0)
   + nvl( length(p_matrl)    - length(replace(p_matrl, ';', ''))    +1, 0)
   + nvl( length(p_suppnbr)  - length(replace(p_suppnbr, ';', ''))  +1, 0)
   + nvl( length(p_mtrlcde)  - length(replace(p_mtrlcde, ';', ''))  +1, 0)
) = 1 THEN
  --LOOP
END IF;

答案 1 :(得分:0)

对于明显的解决方案,有很多话要说。毕竟,大自然给了我们cut'n'paste,而不是使用它?

IF NOT ( (P_suppname is NOT NULL and p_matrl is null and p_suppnbr is NULL and P_mtrlcde is NULL )
    or  (P_suppname is NULL and p_matrl is NOT NULL and p_suppnbr is NULL and P_mtrlcde is NULL )
    or  (P_suppname is NULL and p_matrl is NULL and p_suppnbr is NOT NULL and P_mtrlcde is NULL )
     or  (P_suppname is NULL and p_matrl is NULL and p_suppnbr is NULL and P_mtrlcde is NOT NULL ) )
THEN
     raise_application_error(-20000, 'wrong number of parameters');
ELSE
    .....

这具有表达其意图的巨大好处:它清楚地检查一个且仅一个参数包含值。其他解决方案可能会更加吵闹,但它们会妨碍人们理解他们想要做的事情。


当然,发布的代码会带来一些复杂性。接口显然允许调用程序传递字符串'NULL'而不是传递NULL。此外,尽管p_matrl似乎是一个数字,但它被定义为varchar2,因此调用程序可以传递废话,如'211; 2322'。

解决这些缺陷的正确方法是修复API,使其不接受这样的废话。这是界面设计者的特权,用于指定调用程序应遵守的契约。换句话说,如果调用程序传递'NULL'而不是NULL,则拒绝它们的参数。将p_matrl的数据类型更改为数字。

但是,一旦API在野外和使用中,处理垃圾的负担落在界面设计师的肩上。他们必须包含额外的验证码。这是规格不佳的代价。不幸的是,它通常不是由原始人承担的:设计者的罪行是在维护者身上访问的。

无论如何,要解决这些问题,我们需要声明局部变量并检查/传递参数值。例如:

if p_matrl = 'NULL'
then
     l_matrl := null;
else
    l_matrl := to_number(p_matrl);
end if;

对所有参数进行验证,并在上面的IF语句中使用适当的变量。

答案 2 :(得分:0)

虽然我无法想象会产生这样一个要求的接口类型(或NULL'NULL'的有效值),但这是我如何处理它:

DECLARE 

    cnt NUMBER;

BEGIN

SELECT DECODE(p_suppname, 'NULL',0, DECODE(INSTR(p_suppname,';'),NULL,0,0,1,0)) + 
DECODE(p_matrl, 'NULL', 0, DECODE(INSTR(p_suppname,';'),NULL,0,0,1,0)) + 
DECODE(p_suppnbr, NULL, 0, 1) + 
DECODE(p_mtrlcde, 'NULL', 0, DECODE(INSTR(p_suppname,';'),NULL,0,0,1,0)) into cnt 
from dual;

IF cnt = 1 THEN
    LOOP
        /* do whatever here */
    END LOOP;
END IF;

END;

我假设p_suppnbr是一个数字,其他所有都是字符串 我还假设任何参数都可以为NULL,并且字符串'NULL'等效于NULL值 (我也隐含地假设任何带有分号的参数至少包含2个值)