DBMS scheduler oracle - how to execute a procedure - oracle

I'm loosing my mind. I have a procedure named foo() which takes no arguments. I'd like to execute it, let's say, every 3 minutes. The code I wrote looks like:
BEGIN
dbms_scheduler.create_job(job_name => FooJob,
job_type => 'PLSQL_BLOCK',
job_action => '
BEGIN
foo();
END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=MINUTELY;INTERVAL=3;BYHOUR=17;BYMINUTE=35;',
enabled => TRUE
comments => 'A comment.');
END;
/
This gives me an error: identificator 'applyjobpenalities' should be defined.
I based on this example: How to execute a procedure with DBMS_SCHEDULER.CREATE_JOB procedure
Also:
1) How to execute dbms_output.put_line() after execution of foo();? Is it possible to just put this line strightly away?
2) How to check if procedure foo() is (was) executing on behalf of scheduler?
UPDATE:
Ok so what I've done is:
1) I typed in SQL Plus 'set serveroutput on'
2) I made a procedure:
create or replace procedure proc1
IS
BEGIN
dbms_output.put_line('sth');
end;
/
3) I changed scheduler code to:
BEGIN
dbms_scheduler.create_job( job_name => 'JustATest',
job_type => 'PLSQL_BLOCK',
job_action =>
'BEGIN
proc1();
END;',
start_date => systimestamp + interval '10' second,
repeat_interval => 'FREQ=SECONDLY',
enabled => TRUE);
END;
/
But I can't see any result in SQL Plus. What am I missing? Both procedures compiled succesfully and I can see this job when I type:
SELECT * FROM DBA_SCHEDULER_JOBS;

1) There is no way to extract DBMS_OUTPUT from a scheduled job.
2) To check if FOO was executing, I use the following SQL (extracted from TOAD's "Spool SQL to Screen" option. If you are going to be spending any time at all developing in Oracle, get TOAD for Oracle).
SELECT l.job_name
, l.JOB_SUBNAME
, l.log_id "Log ID"
, l.log_date "Log Date"
, l.operation "Operation"
, l.status "Status"
, l.user_name "User Name"
, l.client_id "Client ID"
, l.global_uid "Global UID"
, r.req_start_date "Required Start Date"
, r.actual_start_date "Actual Start Date"
, r.run_duration "Run Duration"
, r.instance_id "Instance ID"
, r.session_id "Session ID"
, r.slave_pid "Slave PID"
, TO_CHAR (r.cpu_used) "CPU Used"
, r.additional_info "Additional Info (Run)"
FROM dba_scheduler_job_log l, dba_scheduler_job_run_details r
WHERE l.log_id = r.log_id(+)
and l.job_name like 'FooJob'
ORDER BY 1 DESC NULLS LAST;
2b) To see jobs that are currently running:
SELECT *
FROM dba_scheduler_running_jobs;
3) If you want to see results from your job, you need to have your job do something, such as insert a record into a table.

Change Job_action => 'proc1';
And in another notepad type
BEGIN
DBMS_SCHEDULER.RUN_JOB(
JOB_NAME => 'justATest',
USE_CURRENT_SESSION => FALSE);
END;
And then execute the above code

You can see result of dbms_output.put_line() in dba_scheduler_job_run_details column "output".
Put in job action
BEGIN
foo();
dbms_output.put_line( 'foo executed in job' ) ;
END;

Related

How to disable a job in oracle with dbms_scheduler

I created a job which runs in my database successfully with DBMS_SCHEDULER ,but now I need to disable this job, how can i do this?
thanks!
Although the current answers provide a solution to how disable a job, I wanted to go a bit further and explain you how the job is created has an effect on whether the job needs to be disabled in the first place.
I am assuming you are using dbms_scheduler.
Job is created with auto_drop true and enabled true
In this case, once the job is created ( assuming you don't have any start time in the future ) the job executes immediately ( because it is enabled ) and then it is dropped automatically ( auto_drop is true )
SQL> begin
DBMS_SCHEDULER.create_job
(
job_name => 'MY_TEST',
job_type => 'PLSQL_BLOCK',
job_action => 'begin dbms_lock.sleep(5); end;',
enabled => TRUE ,
auto_drop => TRUE
);
end;
/ 2 3 4 5 6 7 8 9 10 11
PL/SQL procedure successfully completed.
SQL>
SQL> exec dbms_lock.sleep(5); -- waiting 5 seconds
PL/SQL procedure successfully completed.
SQL> select job_name,job_action from dba_scheduler_jobs where job_name = 'MY_TEST' ;
no rows selected
SQL>
Job is created with auto_drop to false and enabled to true
In this case, the job runs and it disables itself automatically. In this scenario you don't need to do anything to disable it.
SQL> begin
2 DBMS_SCHEDULER.create_job
3 (
4 job_name => 'MY_TEST',
5 job_type => 'PLSQL_BLOCK',
6 job_action => 'begin dbms_lock.sleep(5); end;',
7 enabled => TRUE ,
8 auto_drop => FALSE
9 );
10* end;
11 /
PL/SQL procedure successfully completed.
select job_name , state, enabled from dba_scheduler_jobs where job_name = 'MY_TEST' ;
JOB_NAME STATE ENABLE
----------------------------------
MY_TEST SUCCEEDED FALSE
Therefore, if your job is enabled is because it has a calendar frequency associated to it, so once has executed, it states enabled until the next time it has to execute
Job with frequency
It means that the job was created to executed based on an expression calendar. In this case, the job executes based on the calendar expression associated to it, and remains enabled and in state SCHEDULED.
SQL> exec dbms_scheduler.drop_job ( job_name => 'MY_TEST' ) ;
PL/SQL procedure successfully completed.
SQL> begin
DBMS_SCHEDULER.create_job
(job_name => 'MY_TEST',
job_type => 'PLSQL_BLOCK',
job_action => 'begin dbms_lock.sleep(5); end;',
enabled => TRUE ,
start_date => systimestamp ,
repeat_interval => 'FREQ=DAILY;BYDAY=MON,TUE,WED,THU,FRI;'
);
end;
/
PL/SQL procedure successfully completed.
SQL> select job_name , state, enabled from dba_scheduler_jobs where job_name = 'MY_TEST' ;
JOB_NAME STATE ENABLE
--------------------------------------
MY_TEST SCHEDULED TRUE
In this case, as it was point out in the other answers:
SQL> exec dbms_scheduler.disable ( 'MY_TEST' ) ;
PL/SQL procedure successfully completed.
SQL> select enabled from dba_scheduler_jobs where job_name = 'MY_TEST' ;
ENABL
-----
FALSE
Summary
If you want to run a job just once and eliminate it, use the option 1 ( auto_drop and enabled )
If you want to run a job and leave it there for run it on demand whenever you want, but disabled. Use option 2 ( auto_drop to false and enabled to true )
Normally you disable jobs that are created with frequency and execute based on some kind of calendar expression.
Obviously, that is just a set of small examples of the many options you have available with dbms_scheduler
Oracle has a good package for schedule jobs.
In your case , you need disable procedure.
Here is the detailed information about dbms_scheduler
Simply call this using oracle new query window like this and your job will be disabled:
begin dbms_scheduler.disable('job-name'); end;
Or in command window :
exec dbms_scheduler.disable('SCHEMA_MNTC_JOB');
You can create a PL/SQL Procedure that disable your job, with the name in parameter
BEGIN
DBMS_SCHEDULER.DISABLE('name_of_your_job');
END;
/
Execute it
EXEC dbms_scheduler.disable('name_of_your_job');
I hope this will solve your problem

What will be the procedure to run a job scheduler to send mails on apex oracle?

I have an apex application where i need to send a notification mail to all the employees on the 5th of every month. So just for the sake of testing i am trying to send a mail in every 30 seconds. I created a job scheduler on a procedure to do the same. Here is the PLSQL code for it.
create or replace procedure send_notification_employee as
cursor c_employee is select * from EMPLOYEE;
r_employee c_employee%ROWTYPE;
begin
open c_employee;
loop
fetch c_employee into r_employee;
exit when c_employee%NOTFOUND;
APEX_MAIL.SEND(
p_to => r_employee.EMPLOYEE_EMAIL,
p_from => 'abc#gmail.com',
p_subj => 'Reminder : Meeting',
p_body => '<Some random message>');
end loop;
close c_employee;
end;
/
begin
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'send_notification',
job_type => 'stored_procedure',
job_action => 'send_notification_employee',
start_date => NULL,
repeat_interval => 'FREQ=SECONDLY;INTERVAL=30',
end_date => NULL);
end;
/
begin
DBMS_SCHEDULER.enable(
name => 'send_notification');
end;
/
I guess the code is correct. The only thing i am not sure of is to how to run this scheduler on the apex oracle application. Should i just execute these statements on the SQL Commands or is there any other way to do it?
Also i tried to execute the same statements in the SQL Commands tab but i don't receive any mails as such. Is there any issue with my code? Thanks in advance.
You need to set the security group if sending the mail from the database rather than from APEX directly. You should also use push_queue at the end of the procedure to clear out the table of unsent mail.
create or replace procedure send_notification_employee as
cursor c_employee is select * from EMPLOYEE;
r_employee c_employee%ROWTYPE;
l_workspace number;
begin
-- Get a valid workspace ID
SELECT MAX(workspace_id) INTO l_workspace FROM apex_applications WHERE application_id = <valid application_id>;
-- Set Workspace
wwv_flow_api.set_security_group_id(l_workspace);
open c_employee;
loop
fetch c_employee into r_employee;
exit when c_employee%NOTFOUND;
APEX_MAIL.SEND(
p_to => r_employee.EMPLOYEE_EMAIL,
p_from => 'abc#gmail.com',
p_subj => 'Reminder : Meeting',
p_body => '<Some random message>');
end loop;
close c_employee;
-- Finally force send
APEX_MAIL.PUSH_QUEUE;
end;
Re. how to execute - it depends on what you want to do. If you just want to run it on the 5th of every month just setup a scheduled job in the db to do it, as you have above. If you want to run on an adhoc basis just create a job in an APEX after submit process that calls the procedure and executes through the database.
As an aside, if you plan to create many mail procedures you may wish to create a helper procedure to get the workspace id / send the mail, and just call it from your other mail procedures.
These queries could be handy (To check if you have the correct set up):
Check if util_smtp is installed:
select * from dba_objects where object_name like 'UTL_SMTP%'
Check privileges:
select grantee , table_name , privilege from dba_tab_privs where table_name = 'UTL_SMTP'
Check open network hosts, ports:
select acl , host , lower_port , upper_port from DBA_NETWORK_ACLS;
Check network privileges:
select acl , principal , privilege , is_grant from DBA_NETWORK_ACL_PRIVILEGES

DBMS SCHEDULER Job with input

Hi I have a stored procedure in oracle that I would like to run periodically. Firstly I got my DBMS_SCHEDULER Job to compile (see below) and I can even see the job be created and drop it though I don't see the result of the stored procedure occur in the table it is supposed to effect and the stored procedure has been tested.
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'JOB_QUERY',
job_type => 'PLSQL_BLOCK', -- see oracle documentation on types --
job_action => 'BEGIN RUNREPORT(''NAME'', ''VERSION'', ''04-Jun-13'', ''11-Jun-13''); END;',
start_date => to_date('2013-08-19 16:35:00', 'YYYY-MM-DD HH24:MI:SS' ),
repeat_interval => 'FREQ=MINUTELY;BYMINUTE=10', -- every 10 minutes.
end_date => NULL,
enabled => TRUE,
comments => 'Daily Jira Query Update');
END;
I was attempting to simply make it run every ten minutes though I see no changes. Also I wanted to be able to pass SYSDATE or the current date to the procedure in the dbms_scheduler job but I cant get it to work with the apostrophes.
Thanks
You have to COMMIT your DML statements. There is no COMMIT in PL/SQL block and I guess in procedure RUNREPORT either.
You don't need an apostrophe around sysdate, it's not a string literal.
job_action => 'BEGIN RUNREPORT(''NAME'', ''VERSION'', sysdate, ''11-Jun-13''); COMMIT; END;',
BYMINUTE does not mean what you would expect. From documentation:
"This specifies the minute on which the job is to run. Valid values are 0 to 59. As an example, 45 means 45 minutes past the chosen hour". What you need is
repeat_interval => 'FREQ=MINUTELY;INTERVAL=10'
You can check next run date and more by querying user_scheduler_jobs.
If you are calling the stored procedure from DMBS Scheduled job you can try below.
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
JOB_NAME => 'SCHEMA.MY_DBMS_SCHEDULED_JOB',
JOB_TYPE => 'STORED_PROCEDURE',
JOB_ACTION => 'SCHEMA.STORED_PROCEDURE_TO_BE_CALLED',
START_DATE => '01-AUG-13 12.00.00 AM',
REPEAT_INTERVAL => 'FREQ=DAILY;BYHOUR=0;BYMINUTE=10',
AUTO_DROP => FALSE,
ENABLED => TRUE,
NUMBER_OF_ARGUMENTS => 0,
COMMENTS => 'Scheduled job to perform updates.');
END;
/
To see if your scheduler log you can use below query.
SELECT * FROM all_SCHEDULER_JOB_LOG
where job_name='MY_DBMS_SCHEDULED_JOB'
order by log_id desc;

automated alert emails using sql developer

A supermarket has many products. When one of these products reaches a quantity of zero an automated email needs to be sent to the manager, showing that this product is out of stock.
I have done the email part( sending email through SQL Developer ). Now I need to set up a loop to keep tracking the products' quantity. How is this loop called? .
APC? i tried this out. but its not working for me
create or replace
procedure check_stock_qty
begin
for r in ( select product_name,product_id from super_market
where pro_qty = 0 )
loop
UTL_MAIL.send(sender => 'blabla#me.com',
recipients => 'blabla#me.com',
subject => 'Test Mail',
message => ( r.product_name ),
mime_type => 'text; charset=us-ascii');
end loop;
end;
------------------------
BEGIN
dbms_scheduler.create_job (job_name => 'stock check',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN check_stock_qty; END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=minutely; interval=5; bysecond=0;',
end_date => NULL,
enabled => TRUE,
END;
the procedure compiled, but win run it. it gives an error " the selected program is in an invalid state for running. recompile the program and try again "
The best way to do this would be to use a database job to periodically check the PRODUCTS table.
First of all you need a stored procedure. Something like this:
create or replace procedure check_stock_qty
begin
for r in ( select product_name from products
where qty = 0 )
loop
your_email_proc_here ( r.product_name );
end loop;
end;
You would then set this to run at regular intervals. As you're using Oracle 11g you should use the DBMS_SCHEDULER API to do this. This calll will run the above stock checker every five minutes:
BEGIN
dbms_scheduler.create_job (
job_name => 'stock check',
job_type => 'PLSQL_BLOCK',
job_action => 'BEGIN check_stock_qty; END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=minutely; interval=5; bysecond=0;',
end_date => NULL,
enabled => TRUE,
END;
/
DBMS_SCHEDULER is pretty sophisticated i.e. complicated but it is well documented. Find out more.

Programming DBA Jobs in Stored procs

I am a little new to programming, so any help is appreciated.
Find below the code of my stored proc to delete a table and also create a DBA job which will run on a hourly basis.
CREATE OR REPLACE procedure DELETE_My_TABLE(myschema varchar2) as
BEGIN
BEGIN
execute immediate 'delete from '||myschema||'.mytable where clause;';
END;
BEGIN
DBMS_SCHEDULER.create_program (
program_name => 'DELETE_My_TABLE',
program_type => 'STORED_PROCEDURE',
program_action => 'execute DELETE_My_TABLE(myschema)',
number_of_arguments => 1,
enabled => FALSE,
comments => 'Program to delete table using a stored procedure.');
DBMS_SCHEDULER.define_program_argument (
program_name => 'DELETE_My_TABLE',
argument_name => 'myschema',
argument_position => 1,
argument_type => 'VARCHAR2',
default_value => 'myschema');
DBMS_SCHEDULER.enable (name => 'DELETE_My_TABLE');
END;
BEGIN
DBMS_SCHEDULER.create_schedule (
schedule_name => 'DELETE_My_TABLE',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=hourly; byminute=0',
end_date => NULL,
comments => 'Hourly Job to purge SEARCH_TEMP_TABLE');
END;
END;
/
Issues:
ERROR at line 1:
ORA-00920: invalid relational operator
ORA-06512: at "MYSCHEMA.DELETE_My_TABLE", line 4
ORA-06512: at line 1
Will the logic (and syntax) work?
One issue I can see is that you need to take the semi-colon out of the EXECUTE IMMEDIATE string:
execute immediate 'delete from '||myschema||'.mytable where clause';
^^
Removed from here
thought I suspect this won't solve your immediate problem, which looks like it's your BEGIN ...END blocks.
For the Oracle Scheduler you normally create a program, once. Next you create a job that has the program as action. You can give that job a schedule like you specified in your code but you have to choose. Either you create a schedule and have the job use it, or you give the job it's own repeat interval.
I happen to know about a book ( Mastering Oracle Scheduler ) that I wrote that could be very helpful.

Resources