Oracle no_data_found 异常未传播到调度程序中
Oracle no_data_found exception is not propagated into the scheduler
令我们沮丧的是,我们发现 no_data_found
异常没有传播到 Oracle 调度程序中。
如果您有一个执行 select x into my_var
的过程并且 select 因 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
异常。问题是:有没有一种方法可以使作业失败而不必更改过程的代码?
这似乎是 DBMS_SCHEDULER
的一个已知问题:参见示例:
- https://blog.pythian.com/no-data-found-success-in-dbms_scheduler/
- https://support.oracle.com/knowledge/Oracle%20Database%20Products/1331778_1.html
- https://community.oracle.com/thread/2344230?start=0&tstart=0
要解决此问题,您可以将作业类型更改为 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
令我们沮丧的是,我们发现 no_data_found
异常没有传播到 Oracle 调度程序中。
如果您有一个执行 select x into my_var
的过程并且 select 因 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
异常。问题是:有没有一种方法可以使作业失败而不必更改过程的代码?
这似乎是 DBMS_SCHEDULER
的一个已知问题:参见示例:
- https://blog.pythian.com/no-data-found-success-in-dbms_scheduler/
- https://support.oracle.com/knowledge/Oracle%20Database%20Products/1331778_1.html
- https://community.oracle.com/thread/2344230?start=0&tstart=0
要解决此问题,您可以将作业类型更改为 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