Chapter 12 · Triggers, Dynamic SQL, Scheduler, Advanced PL/SQL, and Database APIs

DBMS_SCHEDULER Jobs, Programs, Chains, Credentials, Windows, and Operational Observability

Automate idempotent database work with Oracle Scheduler jobs, programs, chains, schedules, windows, and credentials while treating run history, time zones, overlap, failures, and cleanup as part of the design.

Advanced125–145 minutesLocal Scheduler job + failure/history labPrograms/chains/windows/credentials progressively introducedFree local database jobs mandatory; external/remote optionalLast reviewed: August 2026

Learning outcomes

ServiceHub's nightly reconciliation is launched from one application server's operating-system cron. During a deployment the host is replaced, the job silently disappears, and nobody notices for two days. Moving appropriate automation into Oracle Scheduler gives the database a schema object, schedule, owner, run history, failure status, and dependency model—but Scheduler is not “cron inside Oracle.”

01

Create a local database Scheduler job with an explicit owner, job action, schedule, logging, and cleanup policy.

02

Distinguish jobs, programs, schedules, chains, windows, job classes, credentials, and destinations by responsibility.

03

Use USER_SCHEDULER_JOBS and USER_SCHEDULER_JOB_RUN_DETAILS to separate database job state from OS process assumptions.

04

Design idempotency, time-zone behavior, overlap policy, retry/failure notification, and cleanup before enabling automation.

05

Keep credentials/external/remote jobs optional and secret-safe while making the required privileges and topology explicit.

Version, tooling, scope, privilege, and licensing baseline

Mandatory work targets a disposable ServiceHub schema in Oracle AI Database Free 26ai and was reviewed against RU 23.26.3 (July 2026), SQL Developer 26.2, and SQLcl 26.2.1. Free is capped at 2 foreground CPU cores, 2 GB combined SGA/PGA memory, and 12 GB user data and receives no Oracle patches or Oracle Support service requests. The mandatory Chapter 12 path uses local database features only: no Diagnostics/Tuning Pack, RAC, Data Guard, GoldenGate, Exadata, OCI service, remote Scheduler agent, or COMPATIBLE change is required. Stored program/trigger creation requires CREATE PROCEDURE/CREATE TRIGGER as appropriate; Scheduler job creation requires CREATE JOB. Cross-schema API tests use the course identities SERVICEHUB_OWNER and SERVICEHUB_APP with narrow grants.

1. Scheduler objects separate what, when, and dependency

Object Responsibility
Job Executable scheduled unit that connects action, schedule, owner, attributes and state
Program Reusable action definition plus typed arguments
Schedule Reusable time/event schedule
Chain Dependency graph of steps and rules
Window Time interval associated with Scheduler/resource-plan behavior; not a Microsoft/OS window
Credential Authentication object for external/remote jobs/file watchers—not needed by ordinary local database jobs

A local database job runs as its database job owner. Oracle documents that a named credential is ignored for an ordinary local database job; credentials are for external/remote authentication.

2. The action must be idempotent before the schedule is clever

Retries, crash recovery, operator reruns, deployment races, and manual execution can all cause an action to be invoked more than once over its lifetime. Make the business action idempotent through keys/state transitions/merge semantics rather than assuming “Scheduler runs exactly once.”

sql · idempotent tick procedure
CREATE OR REPLACE PROCEDURE servicehub_scheduler_tickAUTHID DEFINERISBEGIN  MERGE INTO servicehub_scheduler_log d  USING (SELECT TRUNC(SYSTIMESTAMP,'MI') AS bucket_ts FROM dual) s  ON (d.bucket_ts=s.bucket_ts)  WHEN NOT MATCHED THEN    INSERT(bucket_ts,logged_at,message)    VALUES(s.bucket_ts,SYSTIMESTAMP,'scheduler tick');  COMMIT; -- This job owns its transaction boundary by design.  DBMS_OUTPUT.PUT_LINE('tick complete');END;/

Unlike an API procedure called inside a user transaction, this background job owns its own unit of work, so an explicit commit can be appropriate. Document that ownership instead of applying a blanket “packages never commit” rule.

3. Create disabled, inspect, then enable

sql · local repeating job
BEGIN  DBMS_SCHEDULER.CREATE_JOB(    job_name        => 'SH12_LOCAL_TICK_JOB',    job_type        => 'STORED_PROCEDURE',    job_action      => 'SERVICEHUB_SCHEDULER_TICK',    start_date      => SYSTIMESTAMP,    repeat_interval => 'FREQ=MINUTELY;INTERVAL=5',    enabled         => FALSE,    auto_drop       => FALSE,    comments        => 'Chapter 12 local job lab'  );  DBMS_SCHEDULER.SET_ATTRIBUTE(    'SH12_LOCAL_TICK_JOB','logging_level',DBMS_SCHEDULER.LOGGING_RUNS  );  DBMS_SCHEDULER.SET_ATTRIBUTE(    'SH12_LOCAL_TICK_JOB','store_output',TRUE  );END;/
sql · inspect before enabling
SELECT job_name,job_type,job_action,state,enabled,       repeat_interval,next_run_date,auto_drop,store_outputFROM user_scheduler_jobsWHERE job_name='SH12_LOCAL_TICK_JOB';

Jobs are created disabled by default unless you explicitly enable them. Validate arguments, privileges, container, time zone, and rollback/disable path before activation.

4. RUN_JOB has two useful test modes

RUN_JOB(..., use_current_session=>TRUE) runs synchronously in your current session and returns errors directly, but Oracle documents that it does not update normal job-run state/history. With FALSE, Scheduler workers execute asynchronously and the run is reflected in Scheduler job/log views.

sql · foreground functional test then asynchronous logged run
BEGIN  DBMS_SCHEDULER.RUN_JOB(    'SH12_LOCAL_TICK_JOB',    use_current_session => TRUE  );END;/BEGIN  DBMS_SCHEDULER.RUN_JOB(    'SH12_LOCAL_TICK_JOB',    use_current_session => FALSE  );END;/-- Requery until the asynchronous run appears.SELECT log_id,job_name,status,actual_start_date,run_duration,       cpu_used,errors,output,additional_infoFROM user_scheduler_job_run_detailsWHERE job_name='SH12_LOCAL_TICK_JOB'ORDER BY log_id DESCFETCH FIRST 5 ROWS ONLY;

5. Time zones and overlap are correctness rules

Scheduler calendaring evaluates repeat intervals into timestamps. Use a region time-zone name in start_date for civil-time schedules that must follow daylight-saving rules rather than a fixed offset. Verify the Scheduler default time zone when start dates are omitted.

For one normally scheduled repeating job, Oracle does not start a new scheduled instance while the current instance is still running. That does not eliminate overlap across two different jobs, manual current-session runs, or multiple systems performing the same business task. If overlap would corrupt data, enforce an application-level/database locking or state-transition policy as well.

sql · container and worker evidence
SELECT SYS_CONTEXT('USERENV','CON_NAME') AS con_name,       DBMS_SCHEDULER.STIME AS scheduler_timeFROM dual;SELECT name,value,ispdb_modifiableFROM v$parameterWHERE name='job_queue_processes';

In a PDB, JOB_QUEUE_PROCESSES=0 prevents Scheduler/DBMS_JOB work in that PDB. The root value can also disable jobs for all PDBs. Do not change this parameter from a single failed job without diagnosing the container and worker state.

6. Programs and chains make dependencies explicit

A named program makes a reusable action/argument contract. A chain is a set of steps plus rules such as “start validate,” “after validate succeeds start publish,” and “end when publish succeeds.” This is preferable to hiding a workflow dependency inside sleeps or one giant procedural job.

sql · compact chain design example
BEGIN  DBMS_SCHEDULER.CREATE_PROGRAM(    program_name   => 'SH12_VALIDATE_PROGRAM',    program_type   => 'STORED_PROCEDURE',    program_action => 'SERVICEHUB_VALIDATE_BATCH',    number_of_arguments => 0,    enabled        => TRUE  );  DBMS_SCHEDULER.CREATE_CHAIN('SH12_RECON_CHAIN');  DBMS_SCHEDULER.DEFINE_CHAIN_STEP(    'SH12_RECON_CHAIN','VALIDATE','SH12_VALIDATE_PROGRAM'  );  DBMS_SCHEDULER.DEFINE_CHAIN_RULE(    'SH12_RECON_CHAIN','TRUE','START VALIDATE'  );  DBMS_SCHEDULER.DEFINE_CHAIN_RULE(    'SH12_RECON_CHAIN','VALIDATE SUCCEEDED','END 0'  );  DBMS_SCHEDULER.ENABLE('SH12_RECON_CHAIN');END;/

This is a design pattern, not part of the minimum lab cleanup below. Chains have additional privileges and lifecycle semantics; use them when dependencies justify the extra object model.

7. Credentials and external/remote jobs are a separate security/topology tier

Current Oracle uses DBMS_CREDENTIAL credential objects for external jobs, remote jobs, and file watchers. Never hard-code a real OS/database password in course source, Git, Scheduler comments, or job arguments. A local database job does not need an OS credential.

sql · optional credential shape — supply secret out-of-band
-- Requires CREATE CREDENTIAL and an external/remote job use case.VARIABLE cred_password VARCHAR2(128)-- Set :cred_password interactively/through a secret mechanism; do not commit it.BEGIN  DBMS_CREDENTIAL.CREATE_CREDENTIAL(    credential_name => 'SH12_REMOTE_CRED',    username        => 'svc_scheduler',    password        => :cred_password  );END;/-- Drop/rotate the credential according to your secret lifecycle.

External/remote jobs add OS agents/destinations/networking and privileges such as CREATE EXTERNAL JOB. They are not required for this Free local chapter lab.

8. Deliberate failure and run-history diagnosis

sql · create a persistent one-time failing job
BEGIN  DBMS_SCHEDULER.CREATE_JOB(    job_name   => 'SH12_FAIL_JOB',    job_type   => 'PLSQL_BLOCK',    job_action => q'[BEGIN RAISE_APPLICATION_ERROR(-20312,'planned scheduler failure'); END;]',    enabled    => FALSE,    auto_drop  => FALSE  );  DBMS_SCHEDULER.RUN_JOB(    'SH12_FAIL_JOB',    use_current_session => FALSE  );END;/SELECT log_id,status,error#,errors,additional_infoFROM user_scheduler_job_run_detailsWHERE job_name='SH12_FAIL_JOB'ORDER BY log_id DESCFETCH FIRST 3 ROWS ONLY;

The database job log is evidence of Scheduler execution. A local job's SLAVE_PID is worker-process metadata; it is not proof that a separate OS cron/systemd task exists.

9. Reproducible cleanup and operational checklist

sql · setup/cleanup support objects
BEGIN EXECUTE IMMEDIATE 'DROP TABLE servicehub_scheduler_log PURGE';EXCEPTION WHEN OTHERS THEN IF SQLCODE != -942 THEN RAISE; END IF; END;/CREATE TABLE servicehub_scheduler_log(  bucket_ts TIMESTAMP PRIMARY KEY,  logged_at TIMESTAMP WITH TIME ZONE NOT NULL,  message VARCHAR2(100) NOT NULL);-- Create SERVICEHUB_SCHEDULER_TICK from section 2, then create/run jobs.BEGIN  DBMS_SCHEDULER.DISABLE('SH12_LOCAL_TICK_JOB',force=>TRUE);EXCEPTION WHEN OTHERS THEN NULL; END;/BEGIN DBMS_SCHEDULER.DROP_JOB('SH12_LOCAL_TICK_JOB',force=>TRUE);EXCEPTION WHEN OTHERS THEN NULL; END;/BEGIN DBMS_SCHEDULER.DROP_JOB('SH12_FAIL_JOB',force=>TRUE);EXCEPTION WHEN OTHERS THEN NULL; END;/BEGIN EXECUTE IMMEDIATE 'DROP PROCEDURE servicehub_scheduler_tick'; EXCEPTION WHEN OTHERS THEN NULL; END;/DROP TABLE servicehub_scheduler_log PURGE;

Production designs also need owner/on-call, schedule time zone, expected duration, concurrency/overlap policy, idempotency key/state, max failures/retry policy, notification channel, run-history retention, disable command, and cleanup of obsolete jobs/programs/chains/credentials.

10. Production judgment

Use Scheduler when database-owned background work benefits from database identity, calendars, dependency chains, run history, and PDB-aware operation. Keep external/remote credentials separated from local jobs, and do not confuse Scheduler windows with OS windows. A scheduled job is an application component: version it, monitor it, and test failure/retry behavior.

No paid option, management pack, remote host, restart, or COMPATIBLE change is required for the local database-job lab. Lesson 4 moves from scheduled procedural work into SQL row sources, comparing streaming pipelined functions and shape-changing polymorphic table functions with simpler SQL abstractions.

Check your understanding

  1. What does a Scheduler program separate from a job?
  2. Does RUN_JOB with use_current_session=TRUE populate normal run history?
  3. Why should civil-time repeating jobs use region names?
  4. Does a normal local database job use a named OS credential?
  5. What does JOB_QUEUE_PROCESSES=0 in a PDB imply?
Review the answers

It defines a reusable executable action and argument contract that jobs/chains can reference.

No. It is a synchronous test path; Oracle documents that ordinary job state/run counters are not updated.

Region names let Scheduler follow applicable daylight-saving transitions; fixed offsets do not encode those rules.

No. Local database jobs run as the database job owner; credentials are for external/remote jobs and file watchers.

Scheduler and DBMS_JOB work cannot run in that PDB, regardless of a nonzero root setting; a zero root setting disables jobs across PDBs too.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.