我可以在具有 if 然后 else if 条件的函数中编写一个循环吗?



content : 我正在编写一个函数来基于 3 个条件返回一个值,但我需要在其中编写一个循环,以便它可以检查传递的每个 id 的条件。 我可以写吗?

法典:

return varchar2
is
a_hldd_code varchar2();
o_result  varchar2();
cursor c_get_hold_codes is 
Select sprhold_hldd_code,sprhold_pidm,stvhldd_desc
from sprhold 
join stvhldd on stvlhdd_pidm=sprhold_pidm
and sprhold_hldd_code like'T%';
Begin 
open c_get_hold_codes;
fetch c_get_hold_codes into a_hldd_code;
close c_get_hold_codes;
if a_hldd_code in ('TL','TY'..) then
o_result := 'Level 1';
else if a_hldd_code not in () then
0_result := 'Level2';
elseif a_hldd_code is null then
o_result :='Level 3';
End if;
return o_result;
end;

[编辑]

如果函数在读取所有记录后落在第一个条件中,则应返回级别 1。 例如,一个 id 有 5 条记录,例如 (TL,T8,T6,T5,T4(,它应该只返回级别 1 而不是级别 2 ...但我的函数返回级别 2..我错过了什么?

create or replace FUNCTION          fwt_get_holds(
i_id  id.table_im%TYPE
) RETURN VARCHAR2 IS
o_level       VARCHAR2(4000);
BEGIN 
o_level := null;
FOR c IN ( SELECT DISTINCT sprhold_hldd_code
FROM
sprhold,
stvhldd
WHERE
stvhldd_code = sprhold_hldd_code
AND sprhold_hldd_code LIKE 'T%'
AND sprhold_to_date >= to_date(sysdate)
AND sprhold_pidm = i_id)
LOOP
IF c.sprhold_hldd_code in ('TF','TB','TY','TL','TS')
then
o_level:='Level 1';
ELSE IF c.sprhold_hldd_code not in ('TF','TB','TY','TL','TS')
then
o_level:='Level 2';
ELSE 
o_level := 'Level 3';
END IF;
RETURN o_level;
END LOOP;

END fwt_get_holds;

在我看来,你想要的任何事情都不会发生。坏消息,嗯?

您编写的代码是错误的 - 不是因为明显的错误,而是 - cursor 的SELECT语句包含 3 列,您正在将其提取到 1varchar2变量中。 3 不能放入 1; 不是那样,就是这样。


此外,你会如何处理函数中的循环?当然,例如,可以这样做(为简单起见切换到光标FOR循环(,但是 - 根据您放置RETURN的位置,您将返回第一个O_RESULT值或最后一个值(请参阅代码中的注释(:

for cur_r in (select sprhold_hldd_code, ...
from sprhold ...
where --> ID condition missing here; ID you're passing, allegedly
)
loop
if cur_r.sprhold_hldd_code in ('TL', 'TY', ...) then ...
-- in a number of IFs, you find what O_RESULT variable is
end if;
-- if you put RETURN here, only one loop iteration will execute
end loop;
-- if you put RETURN here, only the last O_RESULT value will be returned

这意味着您实际上希望在函数外部放置一个循环,即在循环中调用该函数,用于您将要传递给该函数的所有ID。像这样:

function f_result (par_id in number) return varchar2 is
o_result varchar2(20);
begin
select sprhold_hldd_code
into l_sprhold_hldd_code
from sprhold ...
where some_id = par_id;
if l_sprhold_hldd_code in ...
-- find O_RESULT in a number of IFs
end if;
return o_result;
end;

现在在循环中调用它

begin
for cur_r in (select id from some_table where some_condition) loop
dbms_output.put_line('For ID = ' || cur_r.id || ', function returned ' || f_result(cur_r.id));
end loop;
end;

如果以上都无济于事,请尝试改写问题。

我们很难从破碎的代码中对业务逻辑进行逆向工程。更容易理解明确规定的规则。所以这是我对你想要什么的解释:

对于给定的 ID:

  1. 如果level 1具有仅与('TF','TB','TY','TL','TS')匹配的不同代码,则返回
  2. 如果它有其他代码与('TF','TB','TY','TL','TS')不匹配,则返回level 2
  3. 如果它有空代码,则返回level 3
  4. 否则返回level 4(例如,当NO_DATA_FOUND时(
create or replace FUNCTION          fwt_get_holds(
i_id  id.table_im%TYPE
) RETURN VARCHAR2 IS
l_level1 number := 0;
l_level2 number := 0;
l_level3 number := 0;
l_level4 number := 0;
BEGIN 
begin
SELECT count(case when sprhold_hldd_code in ('TF','TB','TY','TL','TS') then 1 end ) as lvl_1
, count(case when sprhold_hldd_code LIKE 'T%' and sprhold_hldd_code not in ('TF','TB','TY','TL','TS') then 1 end ) as lvl_2
, count(case when sprhold_hldd_code is null then 1 end ) as lvl_3
into l_level1
, l_level2
, l_level3
FROM sprhold,
stvhldd
WHERE stvhldd_code = sprhold_hldd_code
AND sprhold_to_date >= trunc(sysdate)
AND sprhold_pidm = i_id;
exception
when others then 
l_level4 := 1;
end;
if l_level4 != 0 then 
return 'level 4';  -- no data found ?
elsif l_level3 != 0 then 
return 'level 3';  -- found some nulls
elsif l_level2 != 0 then 
return 'level 2';  -- found some non-matching codes
else
return 'level 1';   -- found only matching codes
end if; 
END fwt_get_holds;

这很可能不是你想要的。如果是这样,我建议您编辑您的问题以解释您的业务规则,就像我在此答案的顶部所做的那样。

最新更新