通过添加嵌入在 PL-SQL(Oracle 函数)中的 select 子句来处理异常
Posted
技术标签:
【中文标题】通过添加嵌入在 PL-SQL(Oracle 函数)中的 select 子句来处理异常【英文标题】:Handling exceptions by adding select clause embedded inside in PL-SQL(Oracle functions) 【发布时间】:2020-03-09 16:20:12 【问题描述】:我必须在 oracle 中设计一个函数(日期输入,数字输出),在给定条件的情况下执行以下三种情况:
case1: 如果 input_date 匹配 monday_date 然后执行 query1(select from where.. and..) with monday_date 作为输入参数。
case2:如果来自 case(1) 的查询没有返回任何行,则创建新变量 max_input_date1 = input_date+1,然后使用 monday_date 和 max_input_date1 作为输入参数执行 query2(with ..select from table1 left join table2 ..)。
case3:如果来自 case(2) 的查询没有返回任何行,则创建新变量 max_input_date2 = input_date+4,然后使用 monday_date 和 max_input_date2 作为输入参数执行 query2( with..select from table1 left join table2 ..)。
我正在尝试使用异常 - NO_DATA_FOUND 移动到每个案例,但看起来 oracle 函数中的异常子句不执行任何“选择”语句 - 我不完全确定,但它对我不起作用,或者我做错了什么。函数进入异常子句后没有返回任何内容。
我正在寻找有关如何使其工作的建议,无论是否使用异常。请帮忙。这就是我的函数到目前为止的样子
CREATE OR
REPLACE FUNCTION get_dept_no(input_date string)
RETURN NUMBER
IS
dept_no NUMBER;
max_input_date1 date ;
max_input_date2 date ;
delta1 integer := 1;
delta2 integer := 4;
BEGIN
SELECT num
INTO dept_no
FROM table1
WHERE aperiod = 201910
AND trunc(monday_date) = to_date(input_date, 'yyyy-mm-dd');
RETURN dept_no;
EXCEPTION
WHEN NO_DATA_FOUND THEN
max_input_date1 := to_date(input_date, 'yyyy-mm-dd') + delta1;
WITH max as (
SELECT *
FROM table2 adm
GROUP BY aperiod, num
)
SELECT
ma.num INTO dept_no
FROM max ma
LEFT JOIN table1 yw
ON ma.aperiod = yw.aperiod
AND ma.num = yw.num
WHERE trunc(ma.DOJ_date) >= to_date(input_date, 'yyyy-mm-dd')
AND trunc(ma.DOJ_date) <= to_date(max_input_date1, 'yyyy-mm-dd');
raise;
WHEN NO_DATA_FOUND THEN
max_input_date2 := to_date(input_date, 'yyyy-mm-dd') + delta2;
WITH max as (
SELECT *
FROM table2 adm
GROUP BY aperiod, num
)
SELECT
ma.num INTO dept_no
FROM max ma
LEFT JOIN table1 yw
ON ma.aperiod = yw.aperiod
AND ma.num = yw.num
WHERE trunc(ma.DOJ_date) >= to_date(input_date, 'yyyy-mm-dd')
AND trunc(ma.DOJ_date) <= to_date(max_input_date2, 'yyyy-mm-dd');
return dept_no;
END get_dept_no;
【问题讨论】:
不确定我是否关注您的问题。你的函数到底返回了什么?空? 你不能在同一个EXCEPTION部分处理WHEN NO_DATA_FOUND THEN
两次,这将导致错误:“PLS-00483:异常'NO_DATA_FOUND'可能出现在此块中最多一个异常处理程序中”跨度>
请查看How to Ask。将其作为您问题的模板可以大大提高您获得满意答案的机会。在这种情况下,表 DDL 和示例数据以及该数据的预期结果。还有什么结果,但我猜我会冒险“ORA-06503:PL/SQL:函数返回没有值”或“ORA-01403 找不到数据”。
现在,该函数返回一行,满足并执行了 case1,我无法转到 case 2 或 case 3,我需要帮助编写 case 2 和 case 3。当函数进入异常时,它不会在异常部分执行查询并返回 null,它应该返回一行。 @Acroyear
我编译构建函数@Belayer时没有产生错误,但如果你让我知道有什么不清楚的地方,我可以试着解释一下。
【参考方案1】:
我倾向于编写非常小的函数,只做一件事;有时令人惊讶地涉及更多代码,但消除了复杂性 - 似乎是一个矛盾,但不是真的。在这种情况下,我将打破它 3 个内部函数和一个简单的 main. (是的,你可以在函数里面写一个函数)。
create or replace function get_dept_no(input_date IN string)
return number
is
dept_no number;
max_input_date1 date;
max_input_date2 date;
delta1 integer := 1;
delta2 integer := 4;
function get_dept_q1
return number
is
dept_q1_result number;
begin
select num
into dept_q1_result
from table1
where aperiod = 201910
and trunc(monday_date) = to_date(input_date, 'yyyy-mm-dd');
return dept_q1_result;
exception
when no_data_found then
return null;
end get_dept_q1;
function get_dept_q2
return number
is
dept_q2_result number;
begin
max_input_date1 := to_date(input_date, 'yyyy-mm-dd') + delta1;
with max as (
select *
from table2 adm
group by aperiod, num
)
select ma.num
into dept_no
from max ma
left join table1 yw
on ma.aperiod = yw.aperiod
and ma.num = yw.num
where trunc(ma.doj_date) >= to_date(input_date, 'yyyy-mm-dd')
and trunc(ma.doj_date) <= to_date(max_input_date1, 'yyyy-mm-dd');
return dept_q2_result;
exception
when no_data_found then
return null;
end get_dept_q2;
function get_dept_q3
return number
is
dept_q3_result number;
begin
max_input_date1 := to_date(input_date, 'yyyy-mm-dd') + delta1;
with max as (
select *
from table2 adm
group by aperiod, num
)
select ma.num
into dept_q3_result
from max ma
left join table1 yw
on ma.aperiod = yw.aperiod
and ma.num = yw.num
where trunc(ma.doj_date) >= to_date(input_date, 'yyyy-mm-dd')
and trunc(ma.doj_date) <= to_date(max_input_date1, 'yyyy-mm-dd');
return dept_q1_result;
exception
when no_data_found then
return null;
end get_dept_q3;
-- MAIN
begin
dept_no := get_dept_q1;
if dept_no is null
then
dept_no := get_dept_q2;
end if;
if dept_nun is null
then
dept_no := get_dept_q3;
end if;
if dept_num is null
then
raise no_data_found;
end if;
return dept_no;
end get_dept_no;
注意:我没有评估查询,只是重组了原始函数。
【讨论】:
哇,这太棒了!我明白你在说什么,我会试试看。但我认为这是我所需要的,以找到一种构建案例的方法。谢谢你。 @Belayer 会让你知道机智是如何发挥作用的 所以我试了一下,这个结构确实有效,也回答了我的问题。我已将其标记为接受。非常感谢!没有一个案例在函数调用时还没有返回任何结果,但我想我需要弄清楚这里的数据流。就函数而言,它编译和构建没有错误! 乐于助人。这是我经常使用的一种方法。它允许在小块中进行测试/调试,从而使两者都变得更加简单。如果嵌套函数通常有用,我将把它变成模式级别的函数。如果在这里完成,您的主要程序减少到 10-12 左右。免责声明:使用这种方法会产生性能损失。但是,保持代码清晰易懂的能力是值得欣然付出的代价——至少在我获得无法接受的性能水平之前。 完全同意! @Belayer-您能否帮助我理解使用这种结构可能做错了什么,即最初起作用的基本功能(现在是该功能的一种形式)根本不返回任何行?我希望不要为此添加另一个问题.. 我不知道。正如我所指出的,这种结构(我假设您的意思是新的)更容易测试和调试。但这样做需要代码、数据、预期输出和当前输出(即使是没有,如果是这样的话)。为此,我建议发布另一个问题,您可以链接到这个问题。以上是关于通过添加嵌入在 PL-SQL(Oracle 函数)中的 select 子句来处理异常的主要内容,如果未能解决你的问题,请参考以下文章