Oracle 原生 DBMS_JOB 套件以 PL/SQL 方式建立排程,無需外部代理服務,比 SQL Server Agent 更輕量、更原生、更易於程式化控制。
DECLARE
v_jobno NUMBER;
BEGIN
DBMS_JOB.SUBMIT(
job => v_jobno,
what => 'PROC_YKTSJTB;', -- 執行動作:存儲過程名 (含分號)
next_date => TRUNC(SYSDATE + 5/1440, 'MI'), -- 下次執行時間:5 分鐘後對齊分鐘
interval => 'TRUNC(SYSDATE + 1/1440, ''MI'')', -- 間隔:每 1 分鐘 (1/1440 天)
no_parse => FALSE
);
COMMIT; -- 必須提交才生效
DBMS_OUTPUT.PUT_LINE('Job Number: ' || v_jobno);
END;
/
| 參數 | 用途 | 構造技巧 |
|---|---|---|
| WHAT | 執行的 PL/SQL 區塊 | 存儲過程呼叫 'PROC_NAME;'、匿名區塊 'BEGIN ... END;'、SQL 語句需包在 BEGIN/END |
| NEXT_DATE | 首次執行時間 | SYSDATE + n/1440 (n 分鐘後)、TRUNC(SYSDATE)+1+6/24 (明日 06:00)、NEXT_DAY(TRUNC(SYSDATE),'FRIDAY')+9/24 (下周五 09:00) |
| INTERVAL | 重複間隔 (必須為字串表達式) | 'SYSDATE+1' 每日、'SYSDATE+1/24' 每小時、'TRUNC(SYSDATE+1)''MI'')' 每分鐘對齊、'NEXT_DAY(TRUNC(SYSDATE),''MONDAY'')' 每周一 |
-- 每分鐘
'TRUNC(SYSDATE + 1/1440, ''MI'')'
-- 每小時整點
'TRUNC(SYSDATE + 1/24, ''HH'')'
-- 每日 02:00
'TRUNC(SYSDATE + 1) + 2/24'
-- 每週一 03:00
'NEXT_DAY(TRUNC(SYSDATE), ''MONDAY'') + 3/24'
-- 每月 1 號 01:00
'ADD_MONTHS(TRUNC(SYSDATE,''MM''), 1) + 1/24'
-- 工作日每 30 分鐘 (簡易版)
'CASE WHEN TO_CHAR(SYSDATE,''DY'') IN (''SAT'',''SUN'') THEN SYSDATE+1 ELSE SYSDATE+1/48 END'
SELECT job, what, next_date, interval, failures, broken
FROM user_jobs;
SELECT * FROM dba_jobs_running;
SELECT * FROM dba_jobs;
-- 立即執行一次
EXEC DBMS_JOB.RUN(123);
-- 修改間隔
EXEC DBMS_JOB.INTERVAL(123, 'TRUNC(SYSDATE+1)+2/24');
-- 修改下次執行時間
EXEC DBMS_JOB.NEXT_DATE(123, SYSDATE+1/24);
-- 暫停/啟用
EXEC DBMS_JOB.BROKEN(123, TRUE); -- 暫停
EXEC DBMS_JOB.BROKEN(123, FALSE); -- 啟用
-- 移除排程
EXEC DBMS_JOB.REMOVE(123);
| 特性 | DBMS_JOB | DBMS_SCHEDULER |
|---|---|---|
| 複雜排程 (行曆、事件驅動) | 弱 | 強 (Schedule/Window/Event) |
| 錯誤處理與重試 | 手動 | 內建 (max_runs, retry_count) |
| 並行執行控制 | 無 | Resource Manager 整合 |
| 日誌與審計 | 簡易 | 完整 (JOB_LOG, SCHEDULER_JOB_RUN_DETAILS) |
| PL/SQL 相容性 | 全版本 | 10g+ |
建議:簡單週期性任務用 DBMS_JOB 即可;複雜排程、企業級調度請遷移 DBMS_SCHEDULER。
COMMIT → Job 不會生效USER_JOBS.FAILURES > 0 設定告警BROKEN=FALSE 確保不被誤停BEGIN
DBMS_SCHEDULER.CREATE_JOB (
job_name => 'DAILY_STATS_JOB',
job_type => 'STORED_PROCEDURE',
job_action => 'PROC_YKTSJTB',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY; BYHOUR=2; BYMINUTE=0; BYSECOND=0',
enabled => TRUE,
comments => 'Daily statistics collection at 02:00'
);
END;
/
Oracle 排程任務以「提交即生效、字串表達式間隔、字典表監控」三板斧解決 90% 定時執行需求。掌握 INTERVAL 字串構造藝術,讓時間成為你的盟友而非敵人。