Pl Sql 过程在使用 oracle 调度程序进行调度时处理异常

Posted

技术标签:

【中文标题】Pl Sql 过程在使用 oracle 调度程序进行调度时处理异常【英文标题】:Pl Sql Procedure handle exception while scheduled using oracle scheduler 【发布时间】:2015-11-20 08:57:29 【问题描述】:

我已经编写了一个将使用 Oracle 调度程序进行调度的过程,并且正在尝试使用以下异常块来处理异常:

EXCEPTION
   WHEN OTHERS THEN
      raise_application_error(-20001,'An error was encountered - '
      || SQLCODE || ' -ERROR- ' || SQLERRM);
END;

我还想确定如果我使用上述支持团队或 DBA 来了解任何异常情况,他们可以采取适当的措施以及所有事务都应该回滚。

【问题讨论】:

除了掩盖错误发生的行之外,这不会做任何事情。您想要处理错误的目的是什么?如果要将错误记录到文件/表中,那么您应该有一个执行日志记录的错误记录过程(使用 pragmaautonomous_transaction),然后您可以在使用 RAISE 重新引发错误之前从异常块中调用该过程。跨度> 没有特定目的来处理错误,因为它可能是由于未指定性质的不良数据造成的,所以我们只想通知支持团队并让支持团队知道存在一些问题,基本上是一种日志设施 。我不想再创建一个表,并想知道支持团队是否可以使用一种方法每周检查此程序结果,这将告诉他们程序是否成功执行或存在一些问题。 sqlcode 只是ORA 之后的数字,因此串联将ORA-01234: Invalid whatever 变成-1234 -ERROR- ORA-012345: Invalid whatever。我看不出增加了什么价值。 【参考方案1】:

如果异常阻止的唯一原因是通知支持团队 - 不要这样做,因为这完全是多余的。

Oracle 在视图 XX_SCHEDULER_JOB_RUNS / XX_SCHEDULER_JOB_RUN_DETAILS 中记录每个作业运行的结果,其中 XX 是 DBA/ALL/USER 之一(用户包含当前登录用户的所有运行, All 包含当前登录用户允许查看的所有运行,DBA(需要特殊权限)包含数据库中的所有运行。

因此,您的支持团队所要做的就是监控 XX_SCHEDULER_JOB_RUN_DETAILS 并检查状态为 FAILURE 的任何条目。

示例

创建一个总是失败的作业,并运行一次:

begin
  dbms_scheduler.create_job(
      job_name => 'JOB_RAISE_DEMO'
     ,job_type => 'PLSQL_BLOCK'
     ,job_action => 'begin raise_application_error(-20001, ''custom error''); end; '

     ,start_date      => to_timestamp_tz('2015-11-20 13:00:00 Europe/Berlin',
                                         'yyyy-mm-dd hh24:mi:ss tzr')
     ,repeat_interval => null
     ,enabled => TRUE
     ,auto_drop => false);
end;

begin
  dbms_scheduler.run_job('JOB_RAISE_DEMO', use_current_session => false);
end;

然后,检查作业状态:

select log_date, job_name, status, error# 
from user_scheduler_job_run_details 
where job_name = 'JOB_RAISE_DEMO';

这会返回:

LOG_DATE                        JOB_NAME        STATUS  ERROR#
20.11.15 12:35:53,516000 +01:00 JOB_RAISE_DEMO  FAILED  20001

【讨论】:

谢谢,这看起来很有道理,但是我可以像下面这样回滚: 其他人回滚时除外;请告诉我。 DBMS_SCHEDULER 在引发异常时执行自动回滚。试一试,你会发现当过程引发异常时,并没有改变任何数据(当然,除非你的过程本身执行了 COMMIT)。

以上是关于Pl Sql 过程在使用 oracle 调度程序进行调度时处理异常的主要内容,如果未能解决你的问题,请参考以下文章

怎样在pl/sql developer中给oracle添加一个调度作业

使用 PL/SQL 过程在 oracle 10g 中转储表

PL/SQL oracle 过程不返回任何值

Oracle——PL/SQL

oracle SQL语句中怎么样调用存储过程

Oracle实战笔记(第六天)之PL/SQL基础