Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Bhaskar .

Asked: January 01, 2003 - 10:19 pm UTC

Last updated: May 05, 2006 - 2:47 pm UTC

Version: 8.1.7

Viewed 10K+ times! This question is

You Asked

Hi Tom,

I want to submit a job which would execute once a day . The problem is that the procedure I am submitting contains OUT parameters therefore its giving error while executing the job.How jobs having OUT parameter are handled while submiting a job.The procedure gets compiled successfully but gives error while executing.

PROCEDURE INSURANCE_DOWNLOAD_PROC
Argument Name Type In/Out
---------- ----------------------- ------ --------
P_CURRENTDATE DATE IN
P_UID VARCHAR2 IN
ERROR_NO NUMBER IN/OUT
ERROR_TEXT VARCHAR2 IN/OUT

procedure test_dbms as
l_job number;
l_error number;
l_msg varchar2(1000);
l_uid varchar2(100):='BHASKAR';
l_date date :='12-dec-2010';
BEGIN
DBMS_JOB.SUBMIT(l_job,'INSURANCE_DOWNLOAD_PROC( ''12-dec-03'',''bhaskar'',l_error,l_msg);');
commit;
End;

Log Error :

Errors in file /export/home/oracle/app/oracle/admin/uat/bdump/uat_snp0_666.trc:
ORA-12012: error on auto execute of job 4
ORA-06550: line 1, column 121:
PLS-00330: invalid use of type name or subtype name
ORA-06550: line 1, column 93:
PL/SQL: Statement ignored
ORA-06512: at "SYS.DBMS_JOB", line 79
ORA-06512: at "SYS.DBMS_JOB", line 131
ORA-06512: at "LENDING.TEST_DBMS", line 8
ORA-06512: at line 1

I also want to know that how end user will come to know if the job fails.We can see the log file but end user would'nt know about it.

Regards,

Bhaskar.



and Tom said...

procedure test_dbms as
l_error number;
l_msg varchar2(1000);
l_uid varchar2(100):='BHASKAR';
l_date date := to_date( '12-dec-2010', 'dd-mon-yyyy');
BEGIN
INSURANCE_DOWNLOAD_PROC( l_date, l_uid, l_error, l_msg );
if ( l_error = 0 ) then
commit;
else
rollback;
raise_application_error( -20001, l_msg );
end if;
End;



and then in sqlplus:


variable n number
exec dbms_job.submit( :n, 'test_dbms;', sysdate, 'trunc(sysdate)+1+8/24' );


(to run at 8am every day -- change 8 to be the hour you want to run at)


You need to wrap the procedure in yet another procedure that takes the OUT parameters and does something about them. In this case, I think you need to look at the error code and raise an error which will put the error in the alert log and increment the failures column in dba_jobs so you KNOW it is failing.




Rating

  (19 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Bhaskar, January 06, 2003 - 12:59 am UTC

Hi Tom,
Well i executed that thing and it worked fine.
Thanks for the reply !!
Bhaskar


How about no wrapping at all?

Doug, April 25, 2003 - 9:44 pm UTC

Tom, are there any risks with just passing in a simple statement?  

SQL> begin
  2  dbms_job.isubmit(40,'delete from ORDER_SUB where end_date <= sysdate;',
  3  trunc(sysdate),'TRUNC(SYSDATE+1)');
  4  end;
  5  /

It will commit?
It will break appropriately? 

Tom Kyte
April 26, 2003 - 8:22 am UTC

it will work fine.

automate execute procedure

A reader, September 15, 2004 - 3:56 pm UTC

Hi Tom,

I have a procedure sp_testproc which takes 2 input parameters. In order to execute the procedure I will do the foll

exec sp_testproc(input1, input2);

Now I am running this manually in my SQL* Plus sessions. Is it possible for me to just automate this exec proc?

Thanks.


Tom Kyte
September 15, 2004 - 4:12 pm UTC

define "automate this exec proc"

what do you want to do?

Is it possible?

A reader, September 16, 2004 - 4:46 pm UTC

Hi Tom,
I am calling stored procedures (bundled in a package) with different arguments (where procedure is same but argument is different) through a scheduling tool.I want to execute these procedures in parallel. Can I do this?
Call main procedure..
which in turn calls p(1) execute, p(2) execute....
If all successful then main is succussful. The idea is to execute p(1)... in parallel, but controlling through p(main)
Thanks

Tom Kyte
September 16, 2004 - 7:45 pm UTC

what is the scheduling tool

isn't that what a scheduling tool does??

But I am facing some problem....

A reader, September 17, 2004 - 5:25 am UTC

Hi Tom,
You are right that scheduling tool does all this. But when I was monitoring the job in unix, I found that processes are running but not doing much, and CPUs are idle 50% of the time. At that time, I thought to run straight from oracle procedure eliminating any other software in between. But on manually running outside, I found the same problem. What I am doing:
p(a) reads from temp table for a state and product loads data in target
p(b) does same thing with different state and other product
.......
Could it be bottleneck becuase I am inserting in the same target???
I thought that I can issue multiple inserts into the same target in Oracle efficiently or I am missing something?
I also tested that when I run procedures serially or in parralel, the loading time is almost same. Will partitioning in target table with state/product will help??? Is it locking issue etc???
Thanks

Tom Kyte
September 17, 2004 - 9:17 am UTC

there is insufficient data here to diagnose anything (and don't add more).

Do you have any of my books or Cary Millsaps book?

Books....

A reader, September 17, 2004 - 9:11 pm UTC

Thanks Tom.
Can you mention the specific Chapter(s) of your or Cary's books in this context?
Regards

Tom Kyte
September 17, 2004 - 9:12 pm UTC

chapter 10 expert one on one Oracle

all about using 10046 trace to tune an application.

Cary's book -- pages 1 .. infinity



Bit of challenge...

A reader, September 18, 2004 - 1:59 am UTC

Hi Tom,
I had a look at chapter 10 of your book, and Cary's book. I don't think it will be worth spending time on Cary's book to tune for the sake of saving few hours, as the Job is once a month, and takes 10 hours in all.
btw: For smaller set of products, the result is very quick. Does this give some indication to look for low hanging fruit?
Thanks


Tom Kyte
September 18, 2004 - 10:33 am UTC

spending time on Cary's book will help you for the rest of your life.

confusion here on my part, it is not like knowledge learned for task "A" is forgotten never to be applied again?

but hey -- if you say "saving a few hours from 10 isn't worth it", then why are we having this discussion in the first place? apparently, while 10 hours is a long time, it is short enough?




if you multiply the time taken for "small" into "large" (eg: small is 100 products and runs in 5 seconds. large is 100,000. is 5,000 seconds still quick to you?)




Agreed but...

A reader, September 18, 2004 - 6:58 pm UTC

Hi Tom,
Thanks a lot. I fully agree with you that knowledge acquired will never be wasted (and also I admire your help and knowledge too).
The problem here is to deliver something also, which I think I won't be able to deliver if I start reading Cary's book (1...infinity). I will defintely read it (thanks for showing me the light), but unfortunately I have to weigh between either to delay the deliverables by making it in the best way, or deliver something as per target, and then re-visit. The reason I put here because I thought I found the problem and can easily be fixed with your magic help. The findings were:
When I run procedures in parallel
-- Parallel process A
exec P(for state S1, product p1)
product p1 (about couple of thousand rows) -- few minutes
exec P(for state S1, product p2)
product p2 (couple of million rows) -- about 2.5 hours
-- Parallel process B
exec P(for state S2, product p1)
product p1 (about couple of thousand rows) -- few minutes
exec P(for state S2, product p2)
product p2 (couple of million rows; more than s1,p2) -- about 4 hours
-- Parallel process C
exec P(for state S3, product p1)
product p1 (about couple of thousand rows) -- few minutes
exec P(for state S3, product p2)
product p2 (couple of miilion rows; more than s1, p2 and < s2,p2) -- about 3.5 hours
________________
Then, I tried to exec in parallel
p(s1,p2), p(s2,p2) and p(s3,p2), I thought if I am able to utilise parallel processing, it should not take T(s1,p2)+T(s2,p2)+T(s3,p3), but the whole process took around same time - around 10 hours!, and When I was monitoring through vmstat, I found that most of the time running processes were 1 (no blocked, no paging), cpu's 50% idle etc..
The oracle version is 9.2 on AIX 5.2L
Thanks



Tom Kyte
September 19, 2004 - 10:18 am UTC


the only thing I can suggest is a 10046 level 12 trace. what are your applications *waiting* on. Doesn't appear to be CPU, so now you need to find out what.

my chapter 10 is a brief introduction to that.
Carys book is the literal deep dive.

Thanks a lot!

A reader, September 19, 2004 - 4:44 pm UTC

Hi Tom,
Thanks for your help.
I will try based upon chapter 10.
Regards

Scheduling of Job

Jignesh, February 18, 2005 - 5:46 am UTC

Hi Tom,

There is a task which should begin after commit & based on the keys that are updated.

My plan is to implement this using :
1. Create on update trigger
2. Create job in ON UPDATE TRIGGER using dynamic SQL and schedule it to run after say 15 seconds.
3. Delete that job( where ? ? still not clear)

Is there any better way of doing this? ?

Tom Kyte
February 18, 2005 - 8:57 am UTC

where did dynamic sql come into play?


it would look like this:


create table job_parameters( jobid number primary key,
<other inputs needed by your job> );


create or replace trigger
after update on t for each row
declare
l_job number;
begin
dbms_job.submit( l_job, 'my_background_procedure(JOB);' );
insert into job_parameters values ( l_job, :new....... );
end;
/



and your background procedure would resemble:


create or replace procedure my_background_procedure(p_jobid in number)
is
l_rec job_parameters%rowtype;
begin
select * into l_rec from job_parameters where jobid = p_jobid;
....process....
delete from job_parameters where jobid = p_jobid;
commit;
end;
/




that will schedule a one time job (it removes itself all by itself after it successfully completes).

that job (my_background_procedure) will get its unique JOB id as input, we'll have used to that store the parameters for this job occurrence in a table -- that makes this job very "bind variable friendy" (rather than gluing the values into the plsql block itself, generating unique SQL for the job queue process to execute).

We clean up the row in the parameter table and are done.



Please ignore my last review

Jignesh, February 18, 2005 - 7:33 am UTC

Hi Tom,

I have implemented the same thing using autonomous transaction in triggers and things are working now.

Thanks for your time


Tom Kyte
February 18, 2005 - 9:14 am UTC

stop -- stop -- STOP

erase that trigger... totally back up the bus.


autonomous transactions are evil, you *might* be able to use them for auditing -- MAYBE. beyond that, evil.


show me what you are doing and I'll show you how very very very bad it is.

use the above, it is transactional (if you rollback the update, the job goes away). it is *easy*. it is correct. it is SAFE

Here is my code....

Jignesh, February 18, 2005 - 10:33 am UTC

I refered to metalink Note:208599.1 and followed the same :

Trigger :
create or replace trigger trig_rw_server_queue after update on rw_server_queue for each row
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
v_seq_id number;
BEGIN
if :new.status_code = 3 then
v_seq_id := :new.rep_run_id;
p_run_job (v_seq_id);
end if;
END;
/

Procedure :
Create or replace procedure
p_run_job(p_report_id Number) as
Jobid Number := 0;
ProcNm Varchar2(200) := 'pkg_report.UPDATE_STATUS('||p_report_id||')';
Begin
ProcNm := 'Begin '||ProcNm||'; End;';
Dbms_job.Submit(Jobid,ProcNm,Sysdate+1/1440,null);
Commit;
End;
/

And the package.procedure

PROCEDURE UPDATE_STATUS (P_REP_KEY NUMBER) IS
v_job_Id SRW_ONE.Job_Ident;
V_rep_Status SRW_ONE.Status_Record;
P_JOB_ID NUMBER;
P_MESSAGE VARCHAR2(2000);

BEGIN
COMMIT;

BEGIN
SELECT job_id
INTO P_JOB_ID
FROM RW_SERVER_QUEUE
WHERE REP_RUN_ID = P_REP_KEY;
EXCEPTION
WHEN NO_DATA_FOUND THEN
P_MESSAGE := P_REP_KEY||SQLERRM;
RAISE_APPLICATION_ERROR (-20002, sqlerrm);
insert into rw_server_queue ( REP_RUN_ID, JOB_ID, status_text )
values ( P_REP_KEY ,v_job_id.jobid, SUBSTR(P_MESSAGE,1,100));
commit;
END;

v_job_Id.JobID := P_JOB_ID;


SRW_ONE.DEBUGGING := TRUE;
-- myPlist := SRW_PARAMLIST(SRW_PARAMETER('',''));

v_job_Id.ServerName := F_MIC_LOOKUP('SERV_PARA','SERVER');
v_job_Id.GatewayURL := F_MIC_LOOKUP('SERV_PARA','GATEWAY');

V_rep_Status := SRW_ONE.Report_Status(v_job_Id);

UPDATE RW_SERVER_QUEUE
SET status_code = nvl(V_rep_Status.StatusCode,88),
status_text = nvl(V_rep_Status.StatusText,'null')
WHERE rep_run_id = p_rep_key;

dbms_output.put_line(V_rep_Status.JobIdent.JobID);
dbms_output.put_line(V_rep_Status.JobIdent.ServerName);
dbms_output.put_line(V_rep_Status.JobType);
dbms_output.put_line(V_rep_Status.OutputType);
dbms_output.put_line(V_rep_Status.OutputName);
dbms_output.put_line(V_rep_Status.QueuedAt);
dbms_output.put_line(V_rep_Status.StartedAt);
dbms_output.put_line(V_rep_Status.FinishedAt);
dbms_output.put_line(V_rep_Status.ParentJob);
exception when others then
RAISE_APPLICATION_ERROR (-20001, sqlerrm);
END;

The whole story behind this stuff is:
We are calling report using event based report.. from database which runs in background and creates file. After we create file, we need to send those file to users using unix 'uuencode' command and insert into blob. (we are using uuencode because of some security reasons otherwise we would have used rwservlet to send the mails directly from report server). So, in the after report trigger, we are updating the report status... since the status will be 'running report in afterreport trigger' we need something which will do an update after executing that report trigger. So, we have created the above job which will do an update after the job is finished (either successful or failure).



Tom Kyte
February 18, 2005 - 2:17 pm UTC

remove the COMMIT -- why would you commit???? please why would you commit?


let the transaction commit

and then the job will run.

what if the update that fired the trigger rolls back? now you have a job running that should not have run.


If you have 2 rows you update in that table -- how many times might that trigger fire at most? (hint: the answer is NOT 2, it is not 0, it is not 1 -- it is some positive number greater than 2 -- for a 2 row update)

*lose the commit*, you do not need it, you do not want it!

please ignore 'commit' in the above code as I was part of my testing.. Thanks

Jignesh, February 18, 2005 - 10:40 am UTC


Tom Kyte
February 18, 2005 - 2:19 pm UTC

then remove the autonomous transaction!!!!!!!

Thanks

Jignesh, February 21, 2005 - 10:00 am UTC

Thanks Tom... I have removed Autonomous Transaction part from trigger now... I have implemented code like yours.

Changing of next run time

Ram, February 07, 2006 - 4:18 am UTC

Hi Tom,
I have scheduled some procedures to run at 02.45 AM, but, now I want to reschedule to run at different times, so I am giving the following command
dbms_job.change(jobid, null, trunc(sysdate)+1+1/24, 'trunc(sysdate)+1+1/24');
(To run daily at 01.00 AM)And, similarly, I have changed for other jobs also.
and when I query dba_jobs, I am able to see the changed time, but, the job runs only at 02.45 AM everyday. What could be the problem?

Tom Kyte
February 07, 2006 - 5:44 am UTC

show us the last_date, this_date, next_date, interval for these jobs (and of course, use a date format that shows us the TIME bit as well as the date)

Altering the next_date

Ram, February 08, 2006 - 3:44 pm UTC

Please check the last_date, this_date....
JOB LAST_DATE THIS_DATE NEXT_DAT INTERVAL
45 2/8/2006 2:44:04 AM 2/9/2006 2:44:04 AM SYSDATE + 1
46 2/8/2006 2:44:04 AM 2/9/2006 2:44:04 AM SYSDATE + 1
44 2/8/2006 2:44:04 AM 2/9/2006 2:44:04 AM SYSDATE + 1
62 2/8/2006 2:44:04 AM 2/9/2006 2:44:04 AM SYSDATE + 1
61 2/8/2006 2:44:04 AM 2/9/2006 2:44:04 AM SYSDATE + 1

I would like to change the next_date to different timings

Regards,
Ram

Tom Kyte
February 10, 2006 - 8:49 am UTC

it would appear to me, that you did not run the dbms_job.change (and that the interval was not correct in the past - it was sysdate+1 which would cause the job to slide over time)


if you do something like this:


ops$tkyte@ORA10GR2> alter session set nls_date_format = 'dd-mon-yyyy hh24:mi:ss';
 
Session altered.
 
ops$tkyte@ORA10GR2> exec dbms_job.submit( :n, 'null;', trunc(sysdate)+1+1/24*2+1/24/60*45, 'trunc(sysdate)+1+1/24*2+1/24/60*45' );
 
PL/SQL procedure successfully completed.
 
ops$tkyte@ORA10GR2> commit;
 
Commit complete.
 
ops$tkyte@ORA10GR2> select last_date, this_date, next_date, interval from user_jobs;
 
LAST_DATE            THIS_DATE            NEXT_DATE            INTERVAL
-------------------- -------------------- -------------------- ---------------------
                                          11-feb-2006 02:45:00 trunc(sysdate)+1+1/24
                                                               *2+1/24/60*45
 
 
ops$tkyte@ORA10GR2> exec dbms_job.change(:n, null, trunc(sysdate)+1+1/24, 'trunc(sysdate)+1+1/24');
 
PL/SQL procedure successfully completed.
 
ops$tkyte@ORA10GR2> commit;
 
Commit complete.
 
ops$tkyte@ORA10GR2> select last_date, this_date, next_date, interval from user_jobs;
 
LAST_DATE            THIS_DATE            NEXT_DATE            INTERVAL
-------------------- -------------------- -------------------- ---------------------
                                          11-feb-2006 01:00:00 trunc(sysdate)+1+1/24



what do you see (and please, make sure columns line up - I cannot tell what fields are which) 

Changing of next date

Ram, February 12, 2006 - 3:10 pm UTC

Thanks, it is working now. I probably had forgotten to commit

Unable to run dbms_stats

Kumar, May 05, 2006 - 10:17 am UTC

Hi,
I want to schedule stats gathering to every Saturday. I have created a job like this:
 var jobno number;
 begin
  dbms_job.submit(:jobno, 'sys.dbms_stats.gather_schema_stats( ownname=>''SCOTT'', cascade=>TRUE);',next_day(trunc(sysdate),'SATURDAY')+22/24, 'next_day(trunc(sysdate),''SATURDAY'')+22/24');
 commit;
 end;

But, I am getting the error 
Errors in file /ford/app/oracle/admin/FLEETDV/bdump/fleetdv_j000_7835.trc:
ORA-12012: error on auto execute of job 3
ORA-20000: Insufficient privileges to analyze an object in Schema
ORA-06512: at "SYS.DBMS_STATS", line 10583
ORA-06512: at "SYS.DBMS_STATS", line 10751
ORA-06512: at "SYS.DBMS_STATS", line 10805
ORA-06512: at "SYS.DBMS_STATS", line 10782
ORA-06512: at line 1
and in the trace file
ORA-12012: error on auto execute of job 3
ORA-20000: Insufficient privileges to analyze an object in Schema
ORA-06512: at "SYS.DBMS_STATS", line 10583
ORA-06512: at "SYS.DBMS_STATS", line 10751
ORA-06512: at "SYS.DBMS_STATS", line 10805
ORA-06512: at "SYS.DBMS_STATS", line 10782
ORA-06512: at line 1
I have 'Analyze Any' privilege granted through a role.
Also, I am gathering statistics of another schema (SCOTT) through the job. I am able to execute this procedure directly
SQL> execute dbms_stats.gather_schema_stats( ownname=>'SCOTT', cascade=>TRUE);

PL/SQL procedure successfully completed.

What could be wrong ? 

Tom Kyte
May 05, 2006 - 2:47 pm UTC

no roles here - need a direct grant.


create table msg ( id number, x varchar2(50) );
create sequence s;

exec insert into msg values ( s.nextval, 'session = ' || userenv('sessionid') ); for x in ( select * from session_roles ) loop insert into msg values ( s.nextval, 'role = ' || x.role ); end loop;

variable n number
begin
dbms_job.submit( :n,
q'|
insert into msg values ( s.nextval, 'session = ' || userenv('sessionid') ); for x in ( select * from session_roles ) loop insert into msg values ( s.nextval, 'role = ' || x.role ); end loop;
|' );
end;
/
commit;


that'll show you - no roles in the job when it runs.

Unable to run dbms_stats

Kumar, May 05, 2006 - 10:23 am UTC

Hi,
I want to schedule stats gathering to every Saturday. I have created a job like this:
 var jobno number;
 begin
  dbms_job.submit(:jobno, 'sys.dbms_stats.gather_schema_stats( ownname=>''SCOTT'', cascade=>TRUE);',next_day(trunc(sysdate),'SATURDAY')+22/24, 'next_day(trunc(sysdate),''SATURDAY'')+22/24');
 commit;
 end;

But, I am getting the error 
Errors in file /ford/app/oracle/admin/FLEETDV/bdump/fleetdv_j000_7835.trc:
ORA-12012: error on auto execute of job 3
ORA-20000: Insufficient privileges to analyze an object in Schema
ORA-06512: at "SYS.DBMS_STATS", line 10583
ORA-06512: at "SYS.DBMS_STATS", line 10751
ORA-06512: at "SYS.DBMS_STATS", line 10805
ORA-06512: at "SYS.DBMS_STATS", line 10782
ORA-06512: at line 1
and in the trace file
ORA-12012: error on auto execute of job 3
ORA-20000: Insufficient privileges to analyze an object in Schema
ORA-06512: at "SYS.DBMS_STATS", line 10583
ORA-06512: at "SYS.DBMS_STATS", line 10751
ORA-06512: at "SYS.DBMS_STATS", line 10805
ORA-06512: at "SYS.DBMS_STATS", line 10782
ORA-06512: at line 1
I have 'Analyze Any' privilege granted through a role.
Also, I am gathering statistics of another schema (SCOTT) through the job. I am able to execute this procedure directly
SQL> execute dbms_stats.gather_schema_stats( ownname=>'SCOTT', cascade=>TRUE);

PL/SQL procedure successfully completed.

What could be wrong ? 

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library