Reputation: 35
We have discovered, to our dismay, that no_data_found
exceptions are not propagated into the Oracle scheduler.
If you have a procedure that does select x into my_var
and the select fails with no_data_found
, the procedure will fail, but the scheduler program running this procedure will still succeed, as will the chain and the job.
I was wondering if no_data_found
is the only exception affected in this way, or if there are others?
In addition, the only solution we came up with so far is to catch no_data_found within the procedure itself and raise a user-defined exception instead. It does work, but it means that if we want to fail-proof our code we would have to go into every single procedure and introduce this exception handling block.
Can you think of a solution that would not involve code change? Maybe a setting at the database level?
Please see the code below
--------------procedure
create procedure test as
l_var number;
begin
select 0
into l_var
from dual
where 1 = 0;
end;
/
--------------program
BEGIN
dbms_scheduler.create_program (
program_name => 'PRG_TEST',
program_type => 'STORED_PROCEDURE',
program_action => 'TEST',
enabled => TRUE,
);
END;
/
-----------------job
BEGIN
dbms_scheduler.create_job (
job_name => 'JOB_TEST',
program_name => 'PRG_TEST',
enabled => TRUE,
);
END;
/
We are wrapping the procedure into a program which in turn is wrapped into a job. Because we enabled the job it will run right away, and succeed.
However, if we just execute the procedure like this:
begin
test;
end;
It will (correctly) fail - with no_data_found
exception. The question is: is there a way to make the job fail without having to change the code of the procedure?
Upvotes: 1
Views: 552
Reputation: 64949
This appears to be a known issue with DBMS_SCHEDULER
: see for example:
To get around this, you can change the type of the job to PLSQL_BLOCK
. Here's what happens when I create a job, check its status, give it a second or so to run in the background and check again:
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
Upvotes: 2