我试图编写一个包含2个case语句的函数。对于背景,用户可以拥有A,B或A和B两者(但在不同的行上,这就是为什么我不能使用单个案例陈述,除非我使用LISTAGG,我被告知不要做到这一点。
示例数据:
User State
1 A
1 B
2 A
3 B
SQL
CREATE OR REPLACE Function F_Calc_State(code Varchar2, id Number, time varchar2) Return Varchar2 AS
Calc_State(10) := null;
l_A varchar2(10) := null;
l_B varchar2(10) := null;
BEGIN
SELECT CASE WHEN state = 'A' THEN 'A'
ELSE null
END into l_A,
CASE WHEN state = 'B' THEN 'B'
ELSE null
END into l_B
FROM TABLE1
WHERE state in ('A', 'B')
AND TABLE1_CODE = code
AND TABLE1_ID = id
AND TABLE1_TIME = time;
CASE WHEN l_A = 'A' and l_B = 'B' then 'AB'
WHEN l_A = 'A' THEN 'A'
WHEN 1_B = 'B' THEN 'B'
ELSE stafford_recip_ind :='NEITHER';
END CASE;
RETURN Calc_State;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 'NO DATA';
WHEN OTHERS THEN
RETURN SQLERRM ;
END F_Calc_State;`
对于想要的结果,当我输入用户1时,我想要返回AB,对于用户2 = A,用户3 = B.我也尝试过两个不同的select语句块但是无法得到它也可以工作,它会因某种原因而遇到异常处理程序。谢谢!
答案 0 :(得分:2)
如果没有找到数据,以下代码将返回NULL
:
CREATE OR REPLACE Function F_Calc_State (
in_code Varchar2,
in_id Number,
in_time varchar2 -- "time" as a string is highly suspicious
) Return Varchar2
AS
v_ab varchar2(10) := null;
BEGIN
SELECT MAX(CASE WHEN t1.state = 'A' THEN 'A' END) ||
MAX(CASE WHEN t1.state = 'B' THEN 'B' END)
INTO v_AB
FROM TABLE1 t1
WHERE t1.state in ('A', 'B') AND
t1.TABLE1_CODE = in_code AND
t1.TABLE1_ID = in_id AND
t1.TABLE1_TIME = in_time;
RETURN(v_ab);
END; -- F_Calc_State
但是,如果没有找到数据,则不会返回错误。
CREATE OR REPLACE Function F_Calc_State (
in_code Varchar2,
in_id Number,
in_time varchar2 -- "time" as a string is highly suspicious
) Return Varchar2
AS
v_ab varchar2(10) := null;
BEGIN
SELECT MAX(CASE WHEN t1.state = 'A' THEN 'A' END) ||
MAX(CASE WHEN t1.state = 'B' THEN 'B' END)
INTO v_AB
FROM TABLE1 t1
WHERE t1.state in ('A', 'B') AND
t1.TABLE1_CODE = in_code AND
t1.TABLE1_ID = in_id AND
t1.TABLE1_TIME = in_time;
GROUP BY t1.TABLE1_CODE; -- this will return no rows if there are no matches
RETURN(v_ab);
EXCEPTION
WHEN NO_DATA_FOUND THEN RETURN 'NO DATA';
WHEN OTHERS THEN RETURN SQLERRM ;
END; -- F_Calc_State
答案 1 :(得分:1)
使用下面的代码,现在您将只获得一行结果。
SELECT MAX(CASE WHEN state = 'A' THEN 'A'
ELSE null END),
MAX(CASE WHEN state = 'B' THEN 'B'
ELSE null END)
INTO l_A, l_B
FROM TABLE1
WHERE state in ('A', 'B')
AND TABLE1_CODE = code
AND TABLE1_ID = id
AND TABLE1_TIME = time;
答案 2 :(得分:0)
一个非常简单的方法可能是这样的: 目前尚不清楚是否要检查是否存在记录,如在异常块中返回“NO DATA”,而在您的case语句中,您的值为“NEITHER”..无论如何,您可以相应地调整此值:
CREATE OR REPLACE Function F_Calc_State( code varchar2
, id number
, time varchar2
) return varchar2
as
l_count_a number;
l_count_b number;
l_result varchar2(10);
begin
select count(*)
into l_count_a
from table1
where state = 'A'
and table1_code = id
and table1_time = time;
select count(*)
into l_count_b
from table1
where state = 'B'
and table1_code = id
and table1_time = time;
if l_count_a = 0 and l_count_b = 0 then l_result := 'NEITHER';
elsif l_count_a > 0 and l_count_b = 0 then l_result := 'A';
elsif l_count_a = 0 and l_count_b > 0 then l_result := 'B';
elsif l_count_a > 0 and l_count_b > 0 then l_result := 'AB';
else l_result := '';
end if;
return l_result;
end F_Calc_State;