根据用户参数进入循环
Posted
技术标签:
【中文标题】根据用户参数进入循环【英文标题】:Enter the loop based on user parameter 【发布时间】:2012-10-31 12:33:40 【问题描述】:有4个参数.material,Suppliernbr,Suppliername,Materail code。我的查询是如果用户在单个参数中输入任何具有单个值的参数,我需要进入循环。
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
如何做到这一点??
【问题讨论】:
您发布的示例没有意义:'NULL' 与 NULL 相同吗?在第一个示例中,'NULL' 不算作一个值,但在第三个示例中它确实如此。或者你的意思是 '211;2322' 算作两个值?在我看来,您需要重新考虑您的界面。 【参考方案1】:统计每个参数中;
的个数,使用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;
【讨论】:
我认为这不太对。对于问题中给出的前两个示例,IF 语句的总和为零。 这将是错误的 select nvl(length('211') - length(replace('211', ';', '')) ,0), -->2 nvl( length( '211') - 长度(替换('211', ';', '')) ,0), -->3 nvl(长度('NULL') - 长度(替换('null', ';', '')) ,0), -->0 nvl( length(Null) - length(replace(Null, ',', '')) ,0) -->0 来自对偶 @Tobsey 你是对的,我确定了答案。但是,现在它将'NULL'
计为一个参数。这不难解决,但恐怕这样做解决方案会变得太不优雅且难以阅读。【参考方案2】:
对于显而易见的解决方案,有很多话要说。毕竟,大自然给了我们剪切和粘贴,而不是使用它?
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 语句中使用适当的变量。
【讨论】:
【参考方案3】:虽然我无法想象会产生这种要求的接口类型(或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 个值)
【讨论】:
以上是关于根据用户参数进入循环的主要内容,如果未能解决你的问题,请参考以下文章
在自定义 WebAPi 中调用 Azure Speech API 时进入无限循环
让 VBA 循环遍历 Outlook 中的所有收件箱,包括共享收件箱