Oracle调度器未传播no_data_found异常的技术咨询与方案问询
Oracle Scheduler 异常处理问题解答
我来帮你梳理这个Oracle调度器的异常问题,结合官方文档和实际经验给你详细解答:
一、是不是只有NO_DATA_FOUND异常会出现这种情况?
并不是哦。Oracle Scheduler默认会把PL/SQL里一些常见的「预期型异常」当成非致命错误——哪怕这些异常没被过程捕获,调度器也不会标记作业/程序执行失败。除了NO_DATA_FOUND(对应错误码ORA-01403),这类异常还包括:
TOO_MANY_ROWS(ORA-01422):SELECT INTO语句返回多行数据时抛出的异常NO_DATA_NEEDED(ORA-06548):管道函数中提前终止数据返回时触发的异常
Oracle认为这些异常属于业务逻辑里的常见场景,默认不把它们归为作业执行失败的范畴。
二、不用修改过程代码的解决办法
完全不用动你的TEST过程代码,你可以通过配置Oracle Scheduler的属性来实现需求,这里有两种实用方案:
方案1:给单个作业/程序设置失败判定规则
通过DBMS_SCHEDULER.SET_ATTRIBUTE这个包,直接修改作业或者程序的failure_condition属性,指定只要出现ORA-01403(也就是NO_DATA_FOUND),就标记作业失败。
举个例子:
-- 修改JOB_TEST作业的失败条件 BEGIN DBMS_SCHEDULER.SET_ATTRIBUTE( name => 'JOB_TEST', attribute => 'FAILURE_CONDITION', value => 'ERROR_NUMBER = 1403' ); END; / -- 或者直接修改PRG_TEST程序,所有关联这个程序的作业都会自动生效 BEGIN DBMS_SCHEDULER.SET_ATTRIBUTE( name => 'PRG_TEST', attribute => 'FAILURE_CONDITION', value => 'ERROR_NUMBER = 1403' ); END; /
设置好之后,当TEST过程抛出NO_DATA_FOUND异常时,调度器会检测到对应的错误码,直接把作业标记为执行失败。
方案2:创建全局作业类批量管控
如果你有一堆作业都需要处理这类异常,更高效的方式是创建一个自定义「作业类(Job Class)」,把失败判定规则配置在这个类里,然后把所有相关作业关联到这个类就行,不用逐个改作业。
示例代码如下:
-- 先创建自定义作业类 BEGIN DBMS_SCHEDULER.CREATE_JOB_CLASS( job_class_name => 'JC_HANDLE_NODATA_ERROR', failure_condition => 'ERROR_NUMBER = 1403', log_history => 30 -- 保留30天的执行日志,可按需调整 ); END; / -- 把已有的JOB_TEST作业关联到这个类 BEGIN DBMS_SCHEDULER.SET_ATTRIBUTE( name => 'JOB_TEST', attribute => 'JOB_CLASS', value => 'JC_HANDLE_NODATA_ERROR' ); END; / -- 以后新建作业时,直接指定这个作业类就行 BEGIN DBMS_SCHEDULER.CREATE_JOB( job_name => 'JOB_TEST_NEW', program_name => 'PRG_TEST', job_class => 'JC_HANDLE_NODATA_ERROR', enabled => TRUE ); END; /
这种方式适合批量管控,一次配置就能覆盖多个作业。
额外小提示
- 如果需要同时处理多个异常,可以把
failure_condition的值扩展一下,比如写成'ERROR_NUMBER IN (1403, 1422)',这样就能同时捕获NO_DATA_FOUND和TOO_MANY_ROWS异常了。 - 你可以通过下面的SQL查看作业的执行状态和错误细节,验证配置是否生效:
SELECT job_name, status, error#, additional_info FROM DBA_SCHEDULER_JOB_RUN_DETAILS WHERE job_name = 'JOB_TEST' ORDER BY log_date DESC;
内容的提问来源于stack exchange,提问作者Gella
相关产品推荐
相关产品推荐

