通过在 PL-SQL(Oracle 函数)中添加嵌入的 select 子句来处理异常

Handling exceptions by adding select clause embedded inside in PL-SQL(Oracle functions)

我必须在 oracle 中设计一个函数(日期输入,数字输出),它在给定条件的情况下执行以下三种情况:

case1:如果 input_date 匹配 monday_date 然后执行 query1(select from where.. and..) with monday_date 作为输入参数。

case2: 如果从 case(1) returns 查询没有行,则创建新变量 max_input_date1 = input_date+1 然后执行 query2(with ..select from table1 left join table2 ..) with monday_date and max_input_date1 as input param.

case3:如果从 case(2) returns 查询没有行,则创建新变量 max_input_date2 = input_date+4 然后执行 query2( with..select from table1 left join table2 ..) with monday_date and max_input_date2 as input param.

我正在尝试使用异常 - NO_DATA_FOUND 移动到每个案例,但看起来 oracle 函数中的异常子句不执行任何 "select" 语句 - 我不完全确定,但它对我不起作用,或者我做错了什么。函数进入异常子句后不返回任何内容。

我正在寻找有关如何使它工作的建议,无论是否使用异常。请帮忙。这是我的函数到目前为止的样子

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;

我倾向于编写只做一件事的非常小的函数;有时令人惊讶地涉及更多代码,但消除了复杂性 - 似乎是矛盾的,但实际上并非如此。在这种情况下,我会分解它的 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; 

注意:我没有评估查询,只是重组了原始函数。