Oracle には2種類のジョブスケジューリング機能があります。旧来の DBMS_JOB(Oracle 8 以前から)と、Oracle 10g から導入された DBMS_SCHEDULER です。DBMS_SCHEDULER は柔軟なスケジュール指定・エラー時の動作制御・実行ログの管理など機能が豊富で、現在では DBMS_SCHEDULER の使用が推奨されています。
この記事でわかること
- DBMS_SCHEDULER.CREATE_JOB でジョブを作成する方法
- REPEAT_INTERVAL でのスケジュール指定(毎日・毎時・曜日指定など)
- プログラム(CREATE_PROGRAM)とスケジュール(CREATE_SCHEDULE)を分離した設計
- ジョブの有効化・無効化・手動実行・削除
- DBA_SCHEDULER_JOBS・DBA_SCHEDULER_JOB_RUN_DETAILS でのジョブ監視
- 実行エラーの確認と対処法
基本的なジョブの作成(CREATE_JOB)
最もシンプルなジョブは DBMS_SCHEDULER.CREATE_JOB で作成します。job_type に PL/SQL ブロック・ストアドプロシージャ・外部スクリプトなどを指定できます。
毎日深夜2時に実行するジョブを作成する
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'DAILY_CLEANUP_JOB', -- ジョブ名(スキーマ内でユニーク)
job_type => 'PLSQL_BLOCK', -- PL/SQL ブロックを直接指定
job_action => '
BEGIN
-- 不要データの削除処理
DELETE FROM log_table
WHERE created_at < SYSDATE - 90;
COMMIT;
END;
',
start_date => SYSTIMESTAMP, -- 即時開始(最初の実行は次のスケジュール時刻から)
repeat_interval => 'FREQ=DAILY;BYHOUR=2;BYMINUTE=0;BYSECOND=0',
-- 毎日 2:00 に実行
end_date => NULL, -- 終了日なし(永続)
enabled => TRUE, -- 作成と同時に有効化
auto_drop => FALSE, -- 実行後にジョブを自動削除しない
comments => '90日以上前のログデータを毎日削除するジョブ'
);
END;
/
ストアドプロシージャを呼び出すジョブ
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'MONTHLY_REPORT_JOB',
job_type => 'STORED_PROCEDURE', -- ストアドプロシージャを呼び出す
job_action => 'PKG_REPORT.GENERATE_MONTHLY', -- スキーマ.プロシージャ名
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=MONTHLY;BYMONTHDAY=1;BYHOUR=6;BYMINUTE=0;BYSECOND=0',
-- 毎月1日 6:00 に実行
enabled => TRUE,
auto_drop => FALSE,
comments => '月次レポートを毎月1日に生成するジョブ'
);
END;
/
REPEAT_INTERVAL の書き方
REPEAT_INTERVAL は カレンダー式(iCalendar 構文ベース)で指定します。FREQ で繰り返し単位を指定し、BY* でさらに絞り込みます。
| スケジュール | REPEAT_INTERVAL の例 |
|---|---|
| 毎日 0:00 | FREQ=DAILY;BYHOUR=0;BYMINUTE=0;BYSECOND=0 |
| 毎時 30 分 | FREQ=HOURLY;BYMINUTE=30;BYSECOND=0 |
| 5分ごと | FREQ=MINUTELY;INTERVAL=5 |
| 平日(月〜金)17:00 | FREQ=DAILY;BYDAY=MON,TUE,WED,THU,FRI;BYHOUR=17;BYMINUTE=0;BYSECOND=0 |
| 毎月最終日 23:59 | FREQ=MONTHLY;BYMONTHDAY=-1;BYHOUR=23;BYMINUTE=59;BYSECOND=0 |
| 毎週月曜 8:00 | FREQ=WEEKLY;BYDAY=MON;BYHOUR=8;BYMINUTE=0;BYSECOND=0 |
| 毎年4月1日 9:00 | FREQ=YEARLY;BYMONTH=APR;BYMONTHDAY=1;BYHOUR=9;BYMINUTE=0;BYSECOND=0 |
次回実行予定時刻を事前に確認する
-- REPEAT_INTERVAL の検証: 次の実行予定を3件確認する
SELECT NEXT_RUN_DATE
FROM (
SELECT
DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(
'FREQ=WEEKLY;BYDAY=MON;BYHOUR=8;BYMINUTE=0;BYSECOND=0',
SYSTIMESTAMP,
SYSTIMESTAMP,
SYSTIMESTAMP + INTERVAL '90' DAY
) AS NEXT_RUN_DATE
FROM DUAL
CONNECT BY LEVEL <= 3
);
-- ※ EVALUATE_CALENDAR_STRING は直接的な関数ではなく、以下の方法で代用する
次回実行時刻を確認する(正式な方法)
-- DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING で次の実行予定を確認
DECLARE
v_next TIMESTAMP WITH TIME ZONE;
v_current TIMESTAMP WITH TIME ZONE := SYSTIMESTAMP;
BEGIN
FOR i IN 1 .. 5 LOOP
DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(
calendar_string => 'FREQ=DAILY;BYDAY=MON,TUE,WED,THU,FRI;BYHOUR=9;BYMINUTE=0;BYSECOND=0',
start_date => SYSTIMESTAMP,
return_date_after => v_current,
next_run_date => v_next
);
DBMS_OUTPUT.PUT_LINE('次回 ' || i || ': ' || TO_CHAR(v_next, 'YYYY-MM-DD HH24:MI:SS'));
v_current := v_next;
END LOOP;
END;
/
プログラムとスケジュールを分離した設計
同じプロシージャを複数のスケジュールで実行したい場合や、スケジュールを複数ジョブで共有したい場合は、プログラム(CREATE_PROGRAM)とスケジュール(CREATE_SCHEDULE)を分離して作成します。
プログラムとスケジュールを分離して作成する
-- ① プログラムを作成(何を実行するか)
BEGIN
DBMS_SCHEDULER.CREATE_PROGRAM(
program_name => 'PRG_ARCHIVE_DATA',
program_type => 'STORED_PROCEDURE',
program_action => 'PKG_ARCHIVE.RUN',
enabled => TRUE,
comments => 'データアーカイブ処理'
);
END;
/
-- ② スケジュールを作成(いつ実行するか)
BEGIN
DBMS_SCHEDULER.CREATE_SCHEDULE(
schedule_name => 'SCH_NIGHTLY_2AM',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY;BYHOUR=2;BYMINUTE=0;BYSECOND=0',
comments => '毎日深夜2時'
);
END;
/
-- ③ ジョブでプログラムとスケジュールを組み合わせる
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'JOB_ARCHIVE_NIGHTLY',
program_name => 'PRG_ARCHIVE_DATA', -- ①で作成したプログラム
schedule_name => 'SCH_NIGHTLY_2AM', -- ②で作成したスケジュール
enabled => TRUE,
comments => '毎日深夜にアーカイブを実行'
);
END;
/
ジョブの有効化・停止・手動実行・削除
ジョブを操作する基本コマンド
-- ジョブを有効化(CREATE_JOB で enabled=>FALSE にした場合)
EXEC DBMS_SCHEDULER.ENABLE('DAILY_CLEANUP_JOB');
-- ジョブを無効化(スケジュール実行を停止するが削除はしない)
EXEC DBMS_SCHEDULER.DISABLE('DAILY_CLEANUP_JOB');
-- ジョブを手動で今すぐ実行する(テスト・緊急実行)
EXEC DBMS_SCHEDULER.RUN_JOB('DAILY_CLEANUP_JOB');
-- use_current_session => FALSE にするとバックグラウンドで非同期実行
EXEC DBMS_SCHEDULER.RUN_JOB('DAILY_CLEANUP_JOB', use_current_session => FALSE);
-- 実行中のジョブを停止する
EXEC DBMS_SCHEDULER.STOP_JOB('DAILY_CLEANUP_JOB');
-- ジョブを削除する
EXEC DBMS_SCHEDULER.DROP_JOB('DAILY_CLEANUP_JOB');
-- プログラム・スケジュールも削除する
EXEC DBMS_SCHEDULER.DROP_PROGRAM('PRG_ARCHIVE_DATA');
EXEC DBMS_SCHEDULER.DROP_SCHEDULE('SCH_NIGHTLY_2AM');
ジョブの監視(DBA_SCHEDULER_JOBS・実行履歴)
ジョブの状態を確認する
-- 全ジョブの状態確認
SELECT
job_name,
state, -- SCHEDULED / RUNNING / DISABLED / FAILED / SUCCEEDED
enabled,
last_start_date,
last_run_duration,
next_run_date,
run_count,
failure_count,
retry_count
FROM DBA_SCHEDULER_JOBS
WHERE owner = 'MYSCHEMA' -- スキーマ名を指定(自分のジョブは USER_SCHEDULER_JOBS で確認可能)
ORDER BY job_name;
-- 現在実行中のジョブを確認
SELECT
owner,
job_name,
session_id,
running_instance,
elapsed_time
FROM DBA_SCHEDULER_RUNNING_JOBS;
ジョブの実行履歴とエラーを確認する
-- 実行履歴の確認(デフォルトで最新 30 件が保存される)
SELECT
job_name,
status, -- SUCCEEDED / FAILED
error#, -- エラーコード(0 = 正常)
actual_start_date,
run_duration,
additional_info -- エラーの詳細メッセージ
FROM DBA_SCHEDULER_JOB_RUN_DETAILS
WHERE owner = 'MYSCHEMA'
ORDER BY actual_start_date DESC
FETCH FIRST 20 ROWS ONLY;
-- 失敗したジョブだけを確認
SELECT
job_name,
status,
error#,
TO_CHAR(actual_start_date, 'YYYY-MM-DD HH24:MI:SS') AS start_time,
additional_info
FROM DBA_SCHEDULER_JOB_RUN_DETAILS
WHERE owner = 'MYSCHEMA'
AND status = 'FAILED'
ORDER BY actual_start_date DESC;
ジョブのログ保持期間を調整する
DBA_SCHEDULER_JOB_RUN_DETAILS に保存される実行履歴の件数はlog_history で制御します(デフォルト 30 件)。
ジョブのログ保持件数を変更する
-- ジョブごとにログ保持件数を設定する
BEGIN
DBMS_SCHEDULER.SET_ATTRIBUTE(
name => 'DAILY_CLEANUP_JOB',
attribute => 'log_history',
value => 60 -- 直近 60 件の実行履歴を保存
);
END;
/
-- 実行に失敗した場合にリトライ回数を設定する(デフォルト 0)
BEGIN
DBMS_SCHEDULER.SET_ATTRIBUTE(
name => 'DAILY_CLEANUP_JOB',
attribute => 'restartable',
value => TRUE -- 失敗時にリスタート可能にする
);
DBMS_SCHEDULER.SET_ATTRIBUTE(
name => 'DAILY_CLEANUP_JOB',
attribute => 'max_failures',
value => 3 -- 連続 3 回失敗したらジョブを無効化
);
END;
/
DBMS_JOB(旧API)との違い
| 項目 | DBMS_JOB(旧) | DBMS_SCHEDULER(新) |
|---|---|---|
| スケジュール指定 | 次回実行時刻を計算する式(例: SYSDATE + 1/24) | カレンダー式(FREQ=DAILY など) |
| 実行内容 | PL/SQL 文字列のみ | PL/SQL ブロック・ストアドプロシージャ・外部スクリプト |
| 実行履歴 | なし | DBA_SCHEDULER_JOB_RUN_DETAILS で確認可能 |
| エラー処理 | 限定的 | max_failures・restartable など豊富 |
| 確認方法 | DBA_JOBS | DBA_SCHEDULER_JOBS |
| 推奨度 | 非推奨(互換性のためにのみ残存) | 推奨 |
まとめ
- CREATE_JOB:ジョブ名・実行内容(job_type/job_action)・スケジュール(repeat_interval)・enabled を指定して作成する
- REPEAT_INTERVAL:カレンダー式で指定(FREQ=DAILY, BYHOUR, BYMONTHDAY など)。EVALUATE_CALENDAR_STRING で事前検証できる
- プログラムとスケジュールの分離:CREATE_PROGRAM / CREATE_SCHEDULE で再利用性が高まる
- RUN_JOB:手動実行でテストできる(use_current_session=FALSE で非同期実行)
- DBA_SCHEDULER_JOB_RUN_DETAILS:実行履歴・エラーコード・additional_info でエラー原因を確認する
ジョブの状態確認・実行中ジョブの強制停止についてはOracleジョブの確認方法完全ガイドも参照してください。

