代码之家  ›  专栏  ›  技术社区  ›  Gella

Oracle no\u data\u found异常未传播到计划程序

  •  1
  • Gella  · 技术社区  · 7 年前

    令我们沮丧的是,我们发现 no_data_found 异常不会传播到Oracle调度程序中。

    如果你有这样的程序 select x into my_var 选择失败 找不到\u data\u ,过程将失败,但运行此过程的调度程序仍将成功,链和作业也将成功。

    我想知道 找不到\u data\u 唯一的例外是否会以这种方式受到影响,或者是否还有其他例外?

    此外,到目前为止,我们提出的唯一解决方案是捕获过程本身中未找到的\u data\u,并引发用户定义的异常。它确实可以工作,但这意味着如果我们想对代码进行故障证明,我们必须进入每个过程并引入这个异常处理块。

    您能想出一个不涉及代码更改的解决方案吗?可能是数据库级别的设置?

    请参见下面的代码

    --------------程序

    create procedure test as
     l_var number;
     begin
       select 0 
         into l_var 
         from dual 
        where 1 = 0; 
     end;
     /
    

    --------------程序

    BEGIN
      dbms_scheduler.create_program (
        program_name   => 'PRG_TEST',
        program_type   => 'STORED_PROCEDURE',
        program_action => 'TEST',
        enabled        => TRUE,
      );
    END;
    /
    

    -----------------工作

    BEGIN
     dbms_scheduler.create_job (
       job_name             => 'JOB_TEST',
       program_name         => 'PRG_TEST',
       enabled              =>  TRUE,
      );
    END;
    /
    

    我们正在将该过程包装到一个程序中,而该程序又被包装到一个作业中。因为我们启用了该作业,它将立即运行并成功。

    但是,如果我们只执行如下过程:

    begin
       test;
    end;
    

    它将(正确地)失败-使用 找不到\u data\u 例外问题是:有没有一种方法可以在不更改过程代码的情况下使作业失败?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Luke Woodward    7 年前

    这似乎是已知的问题 DBMS_SCHEDULER :参见示例:

    要解决此问题,可以将作业类型更改为 PLSQL_BLOCK . 以下是创建作业、检查其状态、给它一秒钟左右的时间在后台运行并再次检查时发生的情况:

    SQL> create or replace procedure test as
      2  begin
      3    raise no_data_found;
      4  end;
      5  /
    
    Procedure created.
    
    SQL> BEGIN
      2   dbms_scheduler.create_job (
      3     job_name             => 'JOB_TEST',
      4     job_type             => 'PLSQL_BLOCK',
      5     job_action           => 'TEST',
      6     enabled              =>  TRUE,
      7     auto_drop            =>  FALSE
      8    );
      9  END;
     10  /
    
    PL/SQL procedure successfully completed.
    
    SQL> SELECT job_name, state, failure_count FROM user_scheduler_jobs WHERE job_name = 'JOB_TEST';
    
    JOB_NAME                       STATE           FAILURE_COUNT
    ------------------------------ --------------- -------------
    JOB_TEST                       SCHEDULED                   0
    
    SQL> EXEC dbms_lock.sleep(1);
    
    PL/SQL procedure successfully completed.
    
    SQL> SELECT job_name, state, failure_count FROM user_scheduler_jobs WHERE job_name = 'JOB_TEST';
    
    JOB_NAME                       STATE           FAILURE_COUNT
    ------------------------------ --------------- -------------
    JOB_TEST                       FAILED                      1