Associate a scheduler job with a window - oracle

Trying to associate a job with a window. Connection should work using the schedule_name but it does not seem to work.
Reproducible example
creating the window opens every other minute
SQL> begin
2 DBMS_SCHEDULER.CREATE_WINDOW (
3 window_name => 'traffic_window',
4 resource_plan => null,
5 repeat_interval => 'FREQ=minutely;interval=2',
6 duration => interval '1' minute
7 );
8 END;
9 /
PL/SQL procedure successfully completed.
SQL> select WINDOW_NAME,SCHEDULE_NAME,SCHEDULE_TYPE,ENABLED,ACTIVE from all_scheduler_windows;
WINDOW_NAME SCHEDULE_NAME SCHEDULE ENABL ACTIV
------------------------------ ----------------------------------- -------- ----- -----
TRAFFIC_WINDOW CALENDAR TRUE TRUE
OK, associating a job
SQL> exec dbms_scheduler.drop_job('test_window_job',true);
PL/SQL procedure successfully completed.
SQL> begin
2 dbms_scheduler.create_job (
3 job_name => 'test_window_job',
4 job_type => 'PLSQL_BLOCK',
5 job_action => 'begin test_func(70,''start'',0,null); end;',
6 schedule_name => 'traffic_window',
7 enabled => false,
8 auto_drop => true
9 );
10
11 dbms_scheduler.set_attribute ('test_window_job','max_runs',1);
12 dbms_scheduler.set_attribute ('test_window_job','stop_on_window_close',true);
13 end;
14 /
PL/SQL procedure successfully completed.
SQL> exec dbms_scheduler.enable('test_window_job');
BEGIN dbms_scheduler.enable('test_window_job'); END;
*
ERROR at line 1:
ORA-27481: "HAKI.TEST_WINDOW_JOB" has an invalid schedule
ORA-27476: "HAKI.TRAFFIC_WINDOW" does not exist
ORA-06512: at "SYS.DBMS_ISCHED", line 2751
ORA-06512: at "SYS.DBMS_SCHEDULER", line 1794
ORA-06512: at line 1
Docs for create_job clearly state
schedule_name - The name of the schedule, window, or window group
associated with this job.
Whats the problem ???
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Prod
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for 32-bit Windows: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production

You are creating a WINDOW but associating the job with the SCHEDULE.
WINDOW != SCHEDULE
Create a SCHEDULE instead of WINDOW.
Update: actually, it is OK to associate a JOB with a WINDOW. But since the windows are in the SYS schema, you must supply the schema name in the parameter:
schedule_name => 'sys.traffic_window'

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

Oracle DBMS Scheduler change in frequency on weekends

I have created a oracle dbms scheduler to execute a procedure daily at 05 AM, 10 AM, 03 PM and 08 PM. Below is the scheduler code
DBMS_SCHEDULER.CREATE_JOB
(
job_name => 'TEST_JOB'
,start_date => SYSDATE
,repeat_interval => 'FREQ=DAILY; BYHOUR=05,10,15,20; BYMINUTE=00 ;BYSECOND=0;'
,end_date => NULL
,job_class => 'DEFAULT_JOB_CLASS'
,job_type => 'PLSQL_BLOCK'
,enabled => TRUE
,job_action => 'BEGIN INSERT_IN_TABLE; END;'
,comments => 'TEST JOB'
);
now i have to modify the same scheduler to execute the same procedure only twice on weekends and run at same frequency on weekdays.
I don't want to create a different scheduler for the weekend executions because sometimes the procedure takes more than 5 hours to execute.
Please guide me if there is a better way to achieve this.
One option could be to use embedded calendars, so that you can create your own calendar expression.
Let me show you an example
SQL> BEGIN
dbms_scheduler.create_schedule('my_schedule_c_1', repeat_interval =>
'FREQ=DAILY; BYHOUR=05,10,15,20; BYMINUTE=00; BYSECOND=00; ');
dbms_scheduler.create_schedule('my_schedule_c_2', repeat_interval =>
'FREQ=DAILY; BYDAY=SAT,SUN; BYHOUR=05,10; BYMINUTE=00; BYSECOND=00;');
END;
/ 2 3 4 5 6 7
PL/SQL procedure successfully completed.
SQL> begin
DBMS_SCHEDULER.create_schedule ('MY_CALC', repeat_interval =>'my_schedule_c_1, my_schedule_c_2');
END;
/ 2 3 4
PL/SQL procedure successfully completed.
SQL>
Then , you only need to apply this schedule to your job
SQL> begin
2 DBMS_SCHEDULER.CREATE_JOB
(
job_name => 'TEST_JOB'
,start_date => SYSDATE
3 ,repeat_interval => 'MY_CALC'
4 ,end_date => NULL
,job_class => 'DEFAULT_JOB_CLASS'
,job_type => 'PLSQL_BLOCK'
5 6 7 8 9 10 ,enabled => TRUE
,job_action => 'BEGIN NULL; END;'
,comments => 'TEST JOB'
); 11 12 13
14 end;
15 /
PL/SQL procedure successfully completed.
SQL>
This way, my job will run using the MAIN_CALC schedule, which is a combination of the two different frequencies.
Of course, you can always create two jobs, but in 11g there is no option to create incompatibilities, which is an object in DBMS_SCHEDULER 12c onwards that prevents a job to start until the other is completed.
My advice, use a schedule calendar embedded with multiple frequencies

DBMS_PARALLEL_EXECUTE and indirectly given grants on procedure

I just bumped into some strange behaviour of DBMS_PARALLEL_EXECUTE (at least for me). See my preset (executed as SYS):
-- Preset
drop user usr1 cascade;
create user usr1 identified by usr1;
create or replace procedure usr1.do_stuff(p1 in number, p2 in number)
is
begin
dbms_output.put_line('I did stuff!');
end;
/
drop user usr2 cascade;
create user usr2 identified by usr2;
grant connect to usr2;
grant create job to usr2;
drop role stuff_doer cascade;
create role stuff_doer;
grant execute on usr1.do_stuff to stuff_doer;
grant stuff_doer to usr2;
So I created 2 users, the first one has a procedure which is given to stuff_doer role. Later this role is given to usr2.
Then I check it as usr2:
SQL*Plus: Release 11.2.0.4.0 Production on Fri May 22 12:14:10 2020
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Enter user-name: usr2#db
Enter password:
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> set serveroutput on
SQL> set linesize 400
SQL> exec usr1.do_stuff(1,1);
I did stuff!
PL/SQL procedure successfully completed.
SQL> DECLARE
2 l_task_name VARCHAR2(100) := 'task_name';
3 l_splitter VARCHAR2(4000) := 'select 1, 1 from dual';
4 l_exec_stmt VARCHAR2(1000) := 'begin usr1.do_stuff(:start_id, :end_id); end;';
5 BEGIN
6 FOR line IN (SELECT d.task_name
7 FROM user_parallel_execute_tasks d
8 WHERE d.task_name = l_task_name)
9 LOOP
10 dbms_parallel_execute.drop_task(task_name => line.task_name);
11 END LOOP;
12
13 dbms_parallel_execute.create_task(l_task_name);
14 dbms_parallel_execute.create_chunks_by_sql(task_name => l_task_name
15 ,sql_stmt => l_splitter
16 ,by_rowid => FALSE);
17
18 dbms_parallel_execute.run_task(l_task_name
19 ,l_exec_stmt
20 ,dbms_sql.native);
21
22 COMMIT;
23
24 END;
25 /
PL/SQL procedure successfully completed.
SQL> column status format A20
SQL> select status from user_parallel_execute_tasks where task_name = 'task_name';
STATUS
--------------------
FINISHED_WITH_ERROR
SQL> column status format A20
SQL> column error_code format 900000
SQL> column error_message format A60
SQL> select status, ERROR_CODE, ERROR_MESSAGE from user_parallel_execute_chunks e where e.TASK_NAME = 'task_name';
STATUS ERROR_CODE ERROR_MESSAGE
-------------------- ---------- ------------------------------------------------------------
PROCESSED_WITH_ERROR -06550 ORA-06550: line 1, column 7:
PLS-00201: identifier 'USR1.DO_STUFF' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
SQL>
See: when I execute do_stuff procedure directly - it finishes as expected. But when I use DBMS_PARALLEL_EXECUTE I get identifier must be declared error. Am I missing something in granting privileges?
I found here this phrase: The CHUNK_BY_SQL, RUN_TASK, and RESUME_TASK subprograms require a query, and are executed using DBMS_SQL.
I tried to explicitly dbms_sql.parse my statement but it also finished OK.
Any help would be appreciated as I'm not getting current situation. And yes, I can grant privileges directly but still it's something tricky for me.
Roles are not activited by default in PL/SQL stored units (tested with Oracle 19 but it's the same behaviour in older releases since very long time):
SQL> set serveroutput on
SQL> select banner from v$version where rownum=1;
BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
SQL> show user;
USER is "USR2"
SQL> select * from session_roles;
ROLE
--------------------------------------------------------------------------------
CONNECT
SELECT_CATALOG_ROLE
HS_ADMIN_SELECT_ROLE
STUFF_DOER
SQL> --
SQL> begin
2 for r in (select role from session_roles)
3 loop
4 dbms_output.put_line('role=' || r.role);
5 end loop;
6 end;
7 /
role=CONNECT
role=SELECT_CATALOG_ROLE
role=HS_ADMIN_SELECT_ROLE
role=STUFF_DOER
PL/SQL procedure successfully completed.
SQL> show errors
No errors.
SQL> create or replace procedure sr is
2 begin
3 for r in (select role from session_roles)
4 loop
5 dbms_output.put_line('role=' || r.role);
6 end loop;
7 end;
8 /
Procedure created.
SQL> show errors
No errors.
SQL>
SQL> exec sr;
PL/SQL procedure successfully completed.
SQL>
Note the difference between anonymous PL/SQL (which is not stored in the database) and a stored unit (procedure/function stored in the database).
This is the right check is the USR2 can execute the procedure (requires CREATE PROCEDURE privilege)
create procedure stuff as
BEGIN
usr1.do_stuff;
END;
/
SQL> show errors
Errors for PROCEDURE STUFF:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/4 PL/SQL: Statement ignored
3/4 PLS-00201: identifier 'USR1.DO_STUFF' must be declared
I.e. the answer is no, direct execute privilege is required (not via a ROLE).

Run a query based on weekends in oracle

am new to ORACLE; please help
Am trying to run a query which pulls up records based on dates;
if date is monday the query should run thrice; that is for monday, sunday, saturday (previous days also) for others days (tue to thursday only for same day);
First, if you want to run the query three times you'll need to do that in something other than plain SQL: PL-SQL, Java, C#, something.
However if you'd like Saturday and Sunday's figures to be included in Monday's you'll need to do something like a CASE statement to change the Sats & Suns to Mons.
case when (trim(to_char((date), 'Day', 'NLS_DATE_LANGUAGE=ENGLISH'))
in ('Saturday', 'Sunday', 'Monday')) then 'Monday'
else trim(to_char((date), 'Day', 'NLS_DATE_LANGUAGE=ENGLISH'))
end
Am trying to run a query which pulls up records based on dates
For scheduling based on calendering, Oracle provides DBMS_SCHEDULER.
For example, the below job would execute every hour:
SQL> BEGIN
2 DBMS_SCHEDULER.DROP_JOB (JOB_NAME => 'test_full_job_definition');
3 END;
4 /
PL/SQL procedure successfully completed.
SQL>
SQL> BEGIN
2 DBMS_SCHEDULER.create_job (
3 job_name => 'test_full_job_definition',
4 job_type => 'PLSQL_BLOCK',
5 job_action => 'BEGIN my_job_procedure; END;',
6 start_date => SYSTIMESTAMP,
7 repeat_interval => 'freq=hourly; byminute=0; bysecond=0;',
8 end_date => NULL,
9 enabled => TRUE,
10 comments => 'Job defined entirely by the CREATE JOB procedure.');
11 END;
12 /
PL/SQL procedure successfully completed.
SQL>
SQL> SELECT JOB_NAME, ENABLED FROM DBA_SCHEDULER_JOBS where job_name ='TEST_FULL_JOB_DEFINITION'
2 /
JOB_NAME ENABL
---------------------------------------- -----
TEST_FULL_JOB_DEFINITION TRUE
SQL>
More examples here

How to present job_name to DBMS_SCHEDULER.ADD_JOB_EMAIL_NOTIFICATION

I am having trouble adding email notifications to Oracle 11g (11.2.0.1.0). It seems like a bug but I'm really not sure. I've tried doing this using SQL Developer to build the code as well as examples from the internet but it's not working.
I can create and enable a job easily enough:
BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => '"SCHEMA"."test1"',
job_type => 'PLSQL_BLOCK',
job_action => 'begin
null;
end;
',
auto_drop => FALSE
);
DBMS_SCHEDULER.enable(
name => '"SCHEMA"."test1"');
END;
/
anonymous block completed
As a precaution, I remove the job email notification - this works.
BEGIN
DBMS_SCHEDULER.REMOVE_JOB_EMAIL_NOTIFICATION (
job_name => '"SCHEMA"."test1"'
);
end;
/
anonymous block completed
But when I try to add an email notification it's as if it can't find the object, I'm working in my own schema and have the DBA role so I would have thought any potential permission issues should be overcome (though in my own schema I would have assumed I could make scheduled jobs easily enough)
BEGIN
DBMS_SCHEDULER.ADD_JOB_EMAIL_NOTIFICATION (
job_name => '"SCHEMA"."test1"',
recipients => 'email_address#test.com',
events => 'JOB_BROKEN, JOB_CHAIN_STALLED, JOB_FAILED, JOB_OVER_MAX_DUR, JOB_SCH_LIM_REACHED'
);
END;
/
ORA-27476: "SCHEMA.SCHEMA" does not exist
ORA-06512: at "SYS.DBMS_ISCHED", line 4856
ORA-06512: at "SYS.DBMS_ISCHED", line 7117
ORA-01403: no data found
ORA-06512: at "SYS.DBMS_SCHEDULER", line 4030
ORA-06512: at line 3
Note it says SCHEMA.SCHEMA as if it didn't read the line properly. When I change it from '"SCHEMA"."test1"' to 'test1' it still doesn't work but says ORA-27476: "SCHEMA.TEST1" does not exist.
All my jobs work correctly and behave and I have gotten a UTL_MAIL implementation going but I'd really like to get the oracle stuff working for simplicity if possible.
A possible issue is that by default object names in Oracle are case insensitive, unless you surround them with double quotes.
Here is a test case:
SQL> select * from v$version where rownum = 1;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
SQL> create user STACKOVERFLOW identified by STACKOVERFLOW;
User created.
SQL> grant connect, create job to STACKOVERFLOW;
Grant succeeded.
SQL> conn STACKOVERFLOW/STACKOVERFLOW
SQL> l
1 BEGIN
2 DBMS_SCHEDULER.CREATE_JOB (
3 job_name => '"STACKOVERFLOW"."test1"',
4 job_type => 'PLSQL_BLOCK',
5 job_action => 'begin
6 null;
7 end;
8 ',
9 auto_drop => FALSE
10 );
11 DBMS_SCHEDULER.enable(
12 name => '"STACKOVERFLOW"."test1"');
13* END;
SQL> /
PL/SQL procedure successfully completed.
If you name your job "test1" Oracle will create it with a lowercase name. You can confirm this by checking the catalog view dba_scheduler_jobs:
SQL> select owner, job_name from dba_scheduler_jobs where job_name = 'TEST1';
no rows selected
SQL> select owner, job_name from dba_scheduler_jobs where job_name = 'test1';
OWNER JOB_NAME
------------------------------ ------------------------------
STACKOVERFLOW test1
Therefore, this will work:
SQL> l
1 BEGIN
2 DBMS_SCHEDULER.ADD_JOB_EMAIL_NOTIFICATION (
3 job_name => '"STACKOVERFLOW"."test1"',
4 recipients => 'email_address#test.com',
5 events => 'JOB_BROKEN, JOB_CHAIN_STALLED, JOB_FAILED, JOB_OVER_MAX_DUR, JOB_SCH_LIM_REACHED'
6 );
7* END;
SQL> /
PL/SQL procedure successfully completed.
But this won't:
SQL> l
1 BEGIN
2 DBMS_SCHEDULER.ADD_JOB_EMAIL_NOTIFICATION (
3 job_name => '"STACKOVERFLOW".TEST1',
4 recipients => 'email_address#test.com',
5 events => 'JOB_BROKEN, JOB_CHAIN_STALLED, JOB_FAILED, JOB_OVER_MAX_DUR, JOB_SCH_LIM_REACHED'
6 );
7* END;
SQL> /
BEGIN
*
ERROR at line 1:
ORA-27476: "STACKOVERFLOW.STACKOVERFLOW" does not exist
ORA-06512: at "SYS.DBMS_ISCHED", line 4921
ORA-06512: at "SYS.DBMS_ISCHED", line 7613
ORA-01403: no data found
ORA-06512: at "SYS.DBMS_SCHEDULER", line 4063
ORA-06512: at line 2

Resources