【问题标题】:Oracle no_data_found exception is not propagated into the schedulerOracle no_data_found 异常未传播到调度程序中
【发布时间】:2018-06-29 13:24:27
【问题描述】:

令我们失望的是,no_data_found 异常并未传播到 Oracle 调度程序中。

如果您有一个执行select x into my_var 的过程并且选择失败并显示no_data_found,则该过程将失败,但运行此过程的调度程序仍然会成功,链和作业也会成功。

我想知道no_data_found 是否是唯一受到这种影响的异常,或者是否还有其他异常?

此外,到目前为止,我们提出的唯一解决方案是在过程本身中捕获 no_data_found 并引发用户定义的异常。它确实有效,但这意味着如果我们想要对代码进行故障验证,我们将不得不进入每个单独的过程并引入这个异常处理块。

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

请看下面的代码

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

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;

它将(正确地)失败 - no_data_found 异常。问题是:有没有办法让工作失败而不必更改程序的代码?

【问题讨论】:

  • 问题是no_data_found异常不能通过procedure/scheduler屏障。如果根本没有异常处理,调度程序仍然成功。我看不出重新筹集 no_data_found 会有什么帮助。

标签: oracle exception scheduler


【解决方案1】:

这似乎是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

【讨论】:

  • 如果我们将程序定义为PLSQL_BLOCK,建议的解决方案也有效。如果引发no_data_found,程序将正确失败,并将传播到链和作业中。
  • 不过有一个问题:如果我们将程序声明为PLSQL_BLOCK,它就不能有任何参数...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-31
  • 1970-01-01
  • 1970-01-01
  • 2011-04-25
  • 2010-09-18
  • 1970-01-01
相关资源
最近更新 更多