在生產環境中,預存程序的定時自動執行是常見需求。本文詳細對比兩種主流實現方案:作業系統層面的 Shell 腳本搭配 Crontab,與資料庫內建的 DBMS_JOB 套件,提供完整可落地的配置範例。
適用於需執行複雜邏輯、依賴 OS 資源、或跨資料庫協同的場景。
#!/bin/sh
# 環境變數設定
ORACLE_BASE=/oracle/home
ORACLE_HOME=/oracle/home/data
NLS_LANG=american_america.ZHS16GBK
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/oracle/home/data/bin
export ORACLE_BASE ORACLE_HOME NLS_LANG PATH
# 執行 PL/SQL 區塊
sqlplus -s username/password <
# 每天 22:30 執行,日誌導向指定檔案
30 22 * * * /export/home/bss/bss/pr_merge_query_report.sh >> /export/home/bss/log/mergequery.log 2>&1
時間格式:分 時 日 月 週
適用於純資料庫內部邏輯、需緊密整合交易、避免外部依賴的場景。可透過 PL/SQL Developer 等工具圖形化配置,或直接執行 PL/SQL 區塊。
BEGIN
-- 提交作業:每天凌晨 1 點執行
SYS.DBMS_JOB.SUBMIT(
job => :job,
what => 'RATING.JOB_PRESS;',
next_date => TO_DATE('01-01-4000', 'dd-mm-yyyy'), -- 遠期日期配合 interval
interval => 'TRUNC(SYSDATE + 1)'); -- 每天午夜
-- 標記為 broken 狀態(需手動啟用),防止立即執行
SYS.DBMS_JOB.BROKEN(
job => :job,
broken => TRUE,
next_date => TO_DATE('01-01-4000', 'dd-mm-yyyy'));
COMMIT;
END;
關鍵參數說明:
what:要執行的 PL/SQL 程式碼或程序呼叫next_date:首次執行時間interval:重複執行間隔運算式,需回傳下次執行日期broken:TRUE 表示暫停,FALSE 表示啟用| 維度 | Shell + Crontab | DBMS_JOB |
|---|---|---|
| 部署複雜度 | 需 OS 存取權、環境變數配置 | 純資料庫操作,權限較簡單 |
| 可靠性 | 依賴 OS 服務狀態 | 隨資料庫啟停,HA 環境更穩健 |
| 監控與管理 | 查看系統日誌 | 查詢 DBA_JOBS 視圖,支援啟停修改 |
| 跨資料庫協調 | 容易實現 | 需 Database Link 支援 |
| 版本相容性 | 所有版本通用 | 10g+ 建議改用 DBMS_SCHEDULER |
Oracle 10g 及以上版本強烈建議使用功能更強大的 DBMS_SCHEDULER,支援日曆語法、事件驅動、鏈式作業、資源管理等企業級特性。DBMS_JOB 已標記為不推薦,僅為相容性保留。