DBMS_SCHEDULER is an advanced job scheduling and management package in Oracle that offers extensive features and flexibility. It is designed to schedule and manage a wide range of tasks, from simple PL/SQL blocks to complex job chains and external scripts. It was introduced in Oracle 10 and got many improvements until Oracle 12. Here is a summary of its most frequent tasks.

Key Features and Common Tasks

Creating Jobs

Schedule jobs to run PL/SQL blocks, procedures, or external executables.

BEGIN
  DBMS_SCHEDULER.create_job (
    job_name        => 'MY_SCHEDULED_JOB',
    job_type        => 'PLSQL_BLOCK',
    job_action      => 'BEGIN my_procedure; END;',
    start_date      => SYSTIMESTAMP,
    repeat_interval => 'FREQ=DAILY; BYHOUR=10; BYMINUTE=0; BYSECOND=0',
    enabled         => TRUE
  );
END;
/

The repeat_interval parameter in DBMS_SCHEDULER specifies how frequently a job should run. Here are some examples and brief explanations:

# Daily at a Specific Time: This interval sets the job to run every day at 9:00 AM.
'FREQ=DAILY; BYHOUR=9; BYMINUTE=0; BYSECOND=0'


# Weekly on Specific Days: This interval schedules the job to run every Monday and Thursday at 9:00 AM.
'FREQ=WEEKLY; BYDAY=MON,THU; BYHOUR=9; BYMINUTE=0; BYSECOND=0'


# Monthly on a Specific Day: This interval sets the job to run on the 15th day of every month at 10:00 AM.
'FREQ=MONTHLY; BYMONTHDAY=15; BYHOUR=10; BYMINUTE=0; BYSECOND=0'


# Every Hour: This interval schedules the job to run every hour.
'FREQ=HOURLY; INTERVAL=1'


# Every 15 Minutes: This interval sets the job to run every 15 minutes.
'FREQ=MINUTELY; INTERVAL=15'


# Daily on Weekdays Only: This interval schedules the job to run every weekday at 8:00 AM.
'FREQ=DAILY; BYDAY=MON,TUE,WED,THU,FRI; BYHOUR=8; BYMINUTE=0; BYSECOND=0'


# Quarterly on Specific Months: This interval sets the job to run on the 1st day of January, April, July, and October at 12:00 PM.
'FREQ=MONTHLY; BYMONTH=1,4,7,10; BYMONTHDAY=1; BYHOUR=12; BYMINUTE=0; BYSECOND=0'


# Annually on a Specific Date: This interval schedules the job to run once a year on December 31st at 11:59 PM.
'FREQ=YEARLY; BYMONTH=12; BYMONTHDAY=31; BYHOUR=23; BYMINUTE=59; BYSECOND=0'

Creating Schedules:

Define complex and reusable schedules with specific intervals. This is useful for creating standard intervals that can be applied to multiple jobs.

BEGIN
  DBMS_SCHEDULER.create_schedule (
    schedule_name   => 'WEEKLY_SCHEDULE',
    start_date      => SYSTIMESTAMP,
    repeat_interval => 'FREQ=WEEKLY; BYDAY=MON,THU; BYHOUR=9; BYMINUTE=0; BYSECOND=0'
  );
END;
/

BEGIN
  DBMS_SCHEDULER.create_job (
    job_name        => 'MY_WEEKLY_JOB',
    schedule_name   => 'WEEKLY_SCHEDULE',
    job_type        => 'PLSQL_BLOCK',
    job_action      => 'BEGIN my_procedure; END;',
    enabled         => TRUE
  );
END;
/

Managing Jobs:

Enable, disable, and drop jobs.

BEGIN
  DBMS_SCHEDULER.enable('MY_SCHEDULED_JOB');
  DBMS_SCHEDULER.disable('MY_SCHEDULED_JOB');
  DBMS_SCHEDULER.drop_job('MY_SCHEDULED_JOB');
END;
/

Forcing Job Execution:

Run a job immediately.

BEGIN
  DBMS_SCHEDULER.run_job('MY_SCHEDULED_JOB');
END;
/

Monitoring Jobs:

Check job status and execution logs.

SELECT 
  job_name,
  log_date,
  status,
  error#,
  additional_info
FROM 
  dba_scheduler_job_run_details
WHERE 
  job_name = 'MY_SCHEDULED_JOB'
ORDER BY 
  log_date DESC;

Creating Job Chains:

Job chains in Oracle’s DBMS_SCHEDULER is a powerful feature that allows you to define and manage a sequence of related jobs, specifying their execution order and dependencies. This is particularly useful for complex workflows where the completion of one task triggers the next.

# Create the Chain:
BEGIN
  DBMS_SCHEDULER.create_chain(
    chain_name => 'MY_JOB_CHAIN',
    rule_set_name => NULL,
    evaluation_interval => NULL,
    comments => 'Example job chain'
  );
END;
/

# Define Chain Steps:
BEGIN
  DBMS_SCHEDULER.define_chain_step(
    chain_name => 'MY_JOB_CHAIN',
    step_name => 'STEP_1',
    program_name => 'my_program_1'
  );
  DBMS_SCHEDULER.define_chain_step(
    chain_name => 'MY_JOB_CHAIN',
    step_name => 'STEP_2',
    program_name => 'my_program_2'
  );
END;
/

# Define Chain Rules:
BEGIN
  DBMS_SCHEDULER.define_chain_rule(
    chain_name => 'MY_JOB_CHAIN',
    condition => 'TRUE',
    action => 'START STEP_1'
  );
  DBMS_SCHEDULER.define_chain_rule(
    chain_name => 'MY_JOB_CHAIN',
    condition => 'STEP_1 COMPLETED',
    action => 'START STEP_2'
  );
END;
/

# Enable the Chain:
BEGIN
  DBMS_SCHEDULER.enable('MY_JOB_CHAIN');
END;
/

# Schedule or Start the Chain:
BEGIN
  DBMS_SCHEDULER.create_job(
    job_name => 'MY_CHAIN_JOB',
    job_type => 'CHAIN',
    job_action => 'MY_JOB_CHAIN',
    start_date => SYSTIMESTAMP,
    enabled => TRUE
  );
END;
/

The condition parameter in the DBMS_SCHEDULER.define_chain_rule procedure specifies the criteria under which a chain rule will be applied. The condition can reference the state of steps within the chain, such as whether a step has succeeded, failed, or completed. Here are some examples of conditions:

# Always True: This condition always evaluates to true, meaning the rule will always be applied.
'TRUE'

# Step Completed Successfully: This condition checks if a specific step has completed successfully.
'STEP_1 COMPLETED'

# Step Succeeded: This condition checks if a specific step has succeeded.
'STEP_1 SUCCEEDED'

# Step Failed: This condition checks if a specific step has failed.
'STEP_1 FAILED'

# Step Skipped: This condition checks if a specific step was skipped.
'STEP_1 SKIPPED'

# Multiple Steps Completed: This condition checks if multiple steps have completed.
'STEP_1 COMPLETED AND STEP_2 COMPLETED'

# One of Multiple Steps Succeeded: This condition checks if any one of multiple steps has succeeded.
'STEP_1 SUCCEEDED OR STEP_2 SUCCEEDED'

# Step Finished (either succeeded or failed): This condition checks if a specific step has finished, regardless of the outcome.
'STEP_1 FINISHED'

# Chained Conditions: This condition chains multiple conditions together with logical operators.
'(STEP_1 SUCCEEDED OR STEP_2 FAILED) AND STEP_3 COMPLETED'

The action parameter in the DBMS_SCHEDULER.define_chain_rule procedure specifies what action should be taken when the condition of the chain rule is met. This allows for the control of the flow of execution within a job chain, managing how and when each step in the chain is executed. The action parameter can direct the scheduler to start, end, pause, or skip steps, among other actions.

# START step_name: This action starts the specified step when the condition is met.
'START STEP_2'

# END: This action ends the chain execution when the condition is met.
'END'

# PAUSE: This action pauses the chain execution when the condition is met.
'PAUSE'

# SKIP step_name: This action skips the specified step when the condition is met.
'SKIP STEP_2'

# STOP: This action stops the entire chain execution immediately when the condition is met.
'STOP'

DBMS_SCHEDULER.create_event_schedule

The DBMS_SCHEDULER.create_event_schedule procedure in Oracle DBMS_SCHEDULER allows you to create a schedule that triggers based on specific events rather than at fixed time intervals. This feature is particularly useful for jobs that need to run in response to database events or external events, such as file arrivals, message queue notifications, or custom application events.

# Creating a Schedule Based on a Database Table Event:
BEGIN
  DBMS_SCHEDULER.create_event_schedule (
    schedule_name   => 'TABLE_INSERT_SCHEDULE',
    start_date      => SYSTIMESTAMP,
    event_condition => 'tab.user = ''MY_USER'' AND tab.operation = ''INSERT'' AND tab.object_name = ''MY_TABLE''',
    queue_spec      => 'SYS.EVENT_QUEUE',
    comments        => 'Schedule for triggering on table insert'
  );
END;
/

# Creating a Schedule Based on a File Arrival Event:
BEGIN
  DBMS_SCHEDULER.create_event_schedule (
    schedule_name   => 'FILE_ARRIVAL_SCHEDULE',
    start_date      => SYSTIMESTAMP,
    event_condition => 'SYS.FILE_WATCHER_EVENT%FILE_NAME = ''example.txt'' AND SYS.FILE_WATCHER_EVENT%FILE_PATH = ''/mydir''',
    queue_spec      => 'SYS.FILE_WATCHER_QUEUE',
    comments        => 'Schedule for triggering on file arrival'
  );
END;
/

# Creating a Schedule Based on a Message Queue Event:
BEGIN
  DBMS_SCHEDULER.create_event_schedule (
    schedule_name   => 'QUEUE_MESSAGE_SCHEDULE',
    start_date      => SYSTIMESTAMP,
    event_condition => 'tab.user_data LIKE ''%MY_MESSAGE_CONTENT%''',
    queue_spec      => 'MY_MESSAGE_QUEUE',
    comments        => 'Schedule for triggering on message queue event'
  );
END;
/

Using the Event Schedule in a Job

After creating an event schedule, you can use it in a job definition to trigger the job based on the event. Here’s an example of creating a job that uses an event schedule:

BEGIN
  DBMS_SCHEDULER.create_job (
    job_name        => 'MY_EVENT_TRIGGERED_JOB',
    schedule_name   => 'TABLE_INSERT_SCHEDULE',
    job_type        => 'PLSQL_BLOCK',
    job_action      => 'BEGIN my_procedure; END;',
    enabled         => TRUE,
    comments        => 'Job triggered by table insert event'
  );
END;
/

In this example, the job MY_EVENT_TRIGGERED_JOB is triggered by the event defined in the TABLE_INSERT_SCHEDULE, which occurs when a row is inserted into the specified table by the specified user.

Summary

DBMS_SCHEDULER is a powerful tool for scheduling and managing jobs in Oracle. Its advanced features allow for detailed control over job execution, making it suitable for a wide range of applications from simple tasks to complex workflows.

Oracle 19c PL/SQL Packages and Types Reference

Leave a Reply

Discover more from DB-Master

Subscribe now to keep reading and get access to the full archive.

Continue reading