在實際業務中,有時會遇到定時執行某個動作或收集某項資料的情況,這時就需要使用資料庫的定時任務來完成。
DM資料庫支援使用DM作業系統、DBMS_JOB或DBMS_SCHEDULER系統包來建立定時任務。其中DBMS_JOB、DBMS_SCHEDULER是DM相容Oracle定時任務功能的系統包,并且DM提供了相容Oracle定時任務相關視圖的功能。
本章介紹使用DBMS_JOB和DBMS_SCHEDULER建立定時任務的方法。
本章的測試環境:
①作業系統:Window 10(64位)
②資料庫版本:達夢8.1
相關關鍵字:
DBMS_JOB,DBMS_SCHEDULER, DM資料庫,定時任務
方式一
使用DBMS_JOB建立作業
DBMS_JOB是DM相容Oracle定時任務功能的系統包,按指定的時間或間隔執行使用者定義的作業。并相容DBA_JOBS、USER_JOBS、DBA_JOBS_RUNNING等Oracle作業相關的資料字典視圖。
建立DBMS_JOB系統包
DM資料庫安裝完成之後預設不建立DBMS_JOB系統包,如果要使用DBMS_JOB系統包需要手工建立,建立或删除DBMS_JOB系統包文法如下:
void SP_INIT_JOB_SYS(CREATE_FLAG INT)
參數詳解
CREATE_FLAG為1時表示建立DBMS_JOB包;為0表示删除該系統包。
DBMS_JOB相關方法
DBMS_JOB建立JOB有兩種過程,ISUBMIT和SUBMIT,兩者的差別是ISUBMIT的JOB編碼是IN參數,由編碼員指定,SUBMIT的JOB編碼是OUT參數,由系統自動生成。DBMS_JOB提供建立、修改、删除、禁用JOB等功能,詳細功能請參考《DM8系統包使用手冊》。
ISUBMIT過程
ISUBMIT使用特定的JOB編碼送出一個作業。這個過程與SUBMIT過程相似,唯一差別是JOB參數作為IN型參數傳遞(SUBMIT過程JOB參數是OUT類型,由系統自動生産JOB編号)。如果提供的工作号已被使用,将産生一個錯誤。文法如下:
PROCEDUREISUBMIT( JOBIN INT, WHATIN VARCHAR2(1800), NEXT_DATEIN DATETIME, "INTERVAL"IN VARCHAR(100), NO_PARSEIN BOOLEAN DEFAULTFALSE);
參數詳解
JOB使用者指定的工作編号,不能為負數,且必須是不存在的工作編号,唯一。
WHAT表示将被執行的代碼,可以是DMSQL代碼塊和存儲過程。
NEXT_DATEJOB下次運作時間,即何時将運作這個工作。
"INTERVAL"作業間隔,即何時這個工作将被重執行。
NO_PARSE表示此工作在送出時或執行時是否進行文法分析,TRUE訓示此PL/SQL代碼在它第一次執行時應進行文法分析,而FALSE
訓示本PL/SQL代碼應立即進行文法分析。
使用方法
假設我們需要建立一個JOB,第二天淩晨開始運作,每5分鐘運作一次,運作時調用存儲過程p_test_job往t_test表中插入資料。實作步驟參考如下:
1.建立DBMS_JOB系統包 調用SP_INIT_JOB_SYS建立DBMS_JOB系統包: SP_INIT_JOB_SYS(1); 建立完成之後,資料庫模式下面多了SYSJOB模式,該模式屬于SYSDBA使用者,SYSJOB模式擁有DBMS_JOB系統包、相關表和視圖。如下圖所示。
2.賦予使用者相關權限 普通使用者建立JOB需要admin job權限,調用DBMS_JOB系統包需要有執行該包的權限,使用管理者SYSDBA使用者賦予DMHR使用者該權限。語句參考如下:
grant admin job to dmhr;grant execute on dbms_job to dmhr;
3.建立作業
①建立T_TEST表:
create table t_test( id int identity(1,1), inserttime datetime, jobtypevarchar2(30) );
②建立存儲過程P_TEST_JOB往該表插入資料:
create or replace procedure p_test_jobasbegin insert into t_test(inserttime,jobtype) values (sysdate,'DBMS_JOB'); commit;end;
③建立JOB号編碼為1001的定時任務,第二天淩晨開始運作,每5分鐘運作一次:
begin dbms_job.isubmit( job => 1001, what => 'p_test_job;', next_date => trunc(sysdate)+1, "INTERVAL" => 'trunc(sysdate)+1+5/(24*60)'); commit;end;
語句執行完成,檢視USER_JOBS視圖可以看到上述步驟建立的JOB。如果JOB正在執行,可以在DBA_JOBS_RUNNING中看到該JOB運作資料。
方式二:使用DBMS_SCHEDULER建立作業
DBMS_SCHEDULER包也是相容Oracle産品主要作業功能的系統包。DBMS_SCHEDULER包提供一系列排程相關的存儲過程及方法供DMSQL調用,目前主要相容ORACLE的DBMS_SCHEDULER包中常用的方法和資料字典視圖。
與DBMS_JOB相比,DBMS_SCHEDULER包的功能要強大很多,但使用起來相對複雜。很學初學者容易被它的複雜性吓跑,其實我們隻要了解SCHEDULE,PROGRAM和JOB這三個概念,就很容易學會如何使用它。
SCHEDULE表示排程計劃表。指定排程從什麼時間開始,什麼時候結束,以什麼頻度排程。使用DBMS_SCHEDULER.CREATE_SCHEDULE過程建立SCHEDULE。
建立的SCHEDULE對象可以在DBA_SCHEDULER_SCHEDULES或USER_SCHEDULER_SCHEDULES視圖中檢視。
PROGRAM表示排程應該做什麼事情,支援DMSQL塊和存儲過程。使用DBMS_SCHEDULER.CREATE_PROGRAM建立PROGRAM。建立的PROGRAM對象,可以在視圖DBA_SCHEDULER_PROGRAMS或USER_SCHEDULER_PROGRAMS中檢視。
JOB表示按照指定的SCHEDULE,執行指定PROGRAM,完成使用者指定的工作。使用DBMS_SCHEDULER.CREATE_JOB建立JOB。建立的JOB對象,可以在DBA_SCHEDULER_JOBS或USER_SCHEDULER_JOBS視圖中檢視。
建立DBMS_SCHEDULER系統包
DM資料庫安裝完成之後預設不建立DBMS_SCHEDULER系統包,如果要使用該系統包需要手工建立,建立或删除DBMS_SCHEDULER系統包文法如下:
void SP_INIT_DBMS_SCHEDULER_SYS (CREATE_FLAG int)
參數詳解
CREATE_FLAG為1時表示建立DBMS_SCHEDULER包;為0表示删除該系統包。
DBMS_SCHEDULER相關方法
CREATE_SCHEDULE過程
CREATE_SCHEDULE用于建立一個排程。文法如下:
PROCEDURE DBMS_SCHEDULER.CREATE_SCHEDULE(SCHEDULE_NAME IN VARCHAR,START_DATE IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,REPEAT_INTERVAL IN VARCHAR,END_DATE IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,COMMENTS IN VARCHAR DEFAULT NULL);
參數詳解
SCHEDULE_NAME排程名稱。要求在模式下名稱唯一,不能為空。
START_DATE排程第一次有效日期或者時間。對于重複的排程,START_DATE是個參照值,這種情況START_DATE不是排程的開始時間,調用的開始決定于REPEATE_INTERVAL的設定。
REPEATE_INTERVAL排程重複間隔,用于指定調用隔多久重複一次。它是基于月曆文法的表達式。
END_DATE作業停止運作時間。如果為未設定,作業則一直有效。
COMMENTS排程相關的描述或注釋。預設為空。
CREATE_PROGRAM過程
CREATE_PROGRAM過程用于建立一個程式。文法如下:
PROCEDURE DBMS_SCHEDULER.CREATE_PROGRAM(PROGRAM_NAME IN VARCHAR,PROGRAM_TYPE IN VARCHAR,PROGRAM_ACTION IN VARCHAR,NUMBER_OF_ARGUMENTS IN INT DEFAULT 0,ENABLED IN BOOLEAN DEFAULT FALSE,COMMENTS IN VARCHAR DEFAULT NULL);
參數詳解
PROGRAM_NAME程式名稱。不能為空,要求在包模式下名稱中名稱唯一。
PROGRAM_TYPE程式類型。不能為空,支援類型如下:PLSQL_BLOCK:說明程式是一個DMSQL語句塊,即DM的SQL程式設計裡的語句塊。此類型的程式或者作業不允許設定參數個數,也就是說設定的參數個數必須為0;STORED_PROCEURE:說明程式是一個存儲過程。支援存儲過程,不支援帶有傳回值的函數。包含輸入輸出或者輸出參數的存儲過程不支援。
PROGRAM_ACTION定義程式的動作。不能為空。可能的動作如下:對于DMSQL語句塊,程式動作就是去執行DMSQL代碼。對于存儲過程,程式動作是存儲過程的名稱。如果存儲過程與作業不屬于同一個模式,則需要指定存儲過程名稱的時候,指定模式名。
NUMBER_OF_ARGUMENTS定義程式包含的參數的個數。若未設定,則預設為0。一個程式最多可以指定255個參數。
ENABLED指定程式是否以激活的方式建立。若設定為TRUE,則執行合法性檢測,檢測成功,則建立程式并置ENABLED狀态。預設設定為FALSE,程式不以激活的方式建立,可以在程式使用之前通過調用ENABLE過程來激活。
COMMENTS程式的相關評論或者注釋。預設為空。
CREATE_JOB過程
CREATE_JOB過程用來建立作業。支援三種方法建立JOB。
①不使用已經存在的程式(PROGRAM)或者排程(SCHEDULE)建立作業。文法如下:
PROCEDURE DBMS_SCHEDULER.CREATE_JOB(JOB_NAME IN VARCHAR,JOB_TYPE IN VARCHAR,JOB_ACTION IN VARCHAR,NUMBER_OF_ARGUMENTS IN INT DEFAULT 0,START_DATE IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,REPEAT_INTERVAL IN VARCHAR DEFAULT NULL,END_DATE IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,JOB_CLASS IN VARCHAR DEFAULT 'DEFAULT_JOB_CLASS',ENABLED IN BOOLEAN DEFAULT FALSE,AUTO_DROP IN BOOLEAN DEFAULT TRUE,COMMENTS IN VARCHAR DEFAULT NULL,CREDENTIAL_NAME IN VARCHAR DEFAULT NULL,DESTINATION_NAME IN VARCHAR DEFAULT NULL);
②使用命名程式(PROGRAM)和命名排程(SCHEDULE)建立作業。文法如下:
PROCEDURE DBMS_SCHEDULER.CREATE_JOB(JOB_NAME IN VARCHAR,PROGRAM_NAME IN VARCHAR,SCHEDULE_NAME IN VARCHAR,JOB_CLASS IN VARCHAR DEFAULT 'DEFAULT_JOB_CLASS',ENABLED IN BOOLEAN DEFAULT FALSE,AUTO_DROP IN BOOLEAN DEFAULT TRUE,COMMENTS IN VARCHAR DEFAULT NULL,JOB_STYLE IN VARCHAR DEFAULT 'REGULAR',CREDENTIAL_NAME IN VARCHAR DEFAULT NULL,DESTINATION_NAME IN VARCHAR DEFAULT NULL);
③使用命名程式(PROGRAM)和内置排程(SCHEDULE)建立作業。文法如下:
PROCEDURE DBMS_SCHEDULER.CREATE_JOB(JOB_NAME IN VARCHAR,PROGRAM_NAME IN VARCHAR,START_DATE IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,REPEAT_INTERVAL IN VARCHAR DEFAULT NULL,END_DATE IN TIMESTAMP WITH TIME ZONE DEFAULT NULL,JOB_CLASS IN VARCHAR DEFAULT 'DEFAULT_JOB_CLASS',ENABLED IN BOOLEAN DEFAULT FALSE,AUTO_DROP IN BOOLEAN DEFAULT TRUE,COMMENTS IN VARCHAR DEFAULT NULL,JOB_STYLE IN VARCHAR DEFAULT 'REGULAR',CREDENTIAL_NAME IN VARCHAR DEFAULT NULL,DESTINATION_NAME IN VARCHAR DEFAULT NULL);
參數詳解
JOB_NAME 作業名稱。要求在包模式下名稱中名稱唯一,不能為空。可以使用GENERATE_JOB_NAME過程自動生成一個作業名。
JOB_TYPE、JOB_ACTION同CREATE_PROGRAM中PROGRAM_TYPE、PROGRAM_ACTION參數。不能為空。
PROGRAM_NAME,SCHEDULE_NAME 作業使用的PROGRAM和排程名稱。
START_DATE,END_DATE、REPEAT_INTERVAL作業起始、結束日期和執行周期間隔。如果 START_DATE 和 REPEAT_INTERVAL 都為 NULL,表示作業在 ENABLE後立即執行。REPEAT_INTERVAL僅支援月曆文法格式。
ENABLED 指定作業建立時是否啟用。
AUTO_DROP 如果為TRUE,作業自動删除。預設為TRUE。自動删除的條件如下:①作業的結束日期已經過期;②作業不是重複執行作業,并且隻執行一次。如果為NULL,則取值為FALSE,作業不會自動删除。
JOB_CLASS,JOB_STYLE,CREDENTIAL_NAME,DESTINATION_NAME不支援,隻作相容參數用。
月曆表達式
月曆表達式是Linux系統的crontab使用的格式,月曆表達式分為三部分:
第一部分是頻率,即“FREQ”關鍵字,它是必須指定的;取值YEARLY| MONTHLY | WEEKLY | DAILY | HOURLY | MINUTELY | SECONDLY。
第二部分是時間間隔,即“INTERVAL”關鍵字,取值範圍是1-999。它是可選參數;
第三部分是附加的參數,可用于精确地指定日期和時間,也是可選參數。下面這些值都是合法的:BYMONTH,BYWEEKNO, BYYEARDAY, BYMONTHDAY, BYDAY, BYHOUR, BYMINUTE, BYSECOND。
舉幾個簡單的月曆寫法。例如:
每隔10分鐘運作一次:
repeat_interval=> 'FREQ=MINUTELY; INTERVAL=10'
每天1點運作一次
repeat_interval=> 'FREQ=DAILY; BYHOUR=1'
每周的1,3,5運作
repeat_interval=> 'FREQ=WEEKLY; BYDAY=MON,WED,FRI"
每年的3,6,9,12月的1号運作:
repeat_interval=> 'FREQ=YEARLY; BYMONTH=MAR,JUN,SEP,DEC; BYMONTHDAY=1'
每月的最後一天執行一次:
repeat_interval=> 'FREQ=MONTHLY; BYMONTHDAY=-1’
使用方法
前面介紹那麼多,下面分别從CREATE_JOB的三種方法上介紹JOB的建立。實作步驟參考如下:
1.建立DBMS_SCHEDULER系統包
調用SP_INIT_DBMS_SCHEDULER_SYS建立DBMS_SCHEDULER系統包:
SP_INIT_DBMS_SCHEDULER_SYS(1);
建立完成之後,資料庫模式下面多了SCHEDULER模式,該模式屬于SYSDBA使用者,SCHEDULER模式擁有DBMS_SCHEDULER系統包、相關表和視圖。如下圖所示。
2.賦予使用者相關權限
調用DBMS_SCHEDULER系統包需要有執行該包的權限,使用管理者SYSDBA使用者賦予DMHR使用者該權限。語句參考如下:
grant execute on dbms_scheduler to dmhr;
3.建立程式和作業
建立存儲過程P_TEST_SCHEDULER往該表插入資料:
create or replace procedure p_test_schedulerasbegin insertintot_test(inserttime,jobtype) values(sysdate,'DBMS_SCHEDULER'); commit;end;
①不使用程式和排程來建立JOB 建立TEST_SCHEDULERJOB1作業,直接使用job_action、job_type、repeat_interval指定作業的類型和動作和執行周期(每10分鐘執行一次,30秒時執行)。
begin dbms_scheduler.create_job( job_name => 'test_schedulerjob1', job_type => 'STORED_PROCEDURE', job_action => 'p_test_scheduler', repeat_interval => 'FREQ=minutely;INTERVAL=10;bysecond=30', enabled => TRUE); commit;end;
②使用程式、不使用排程來建立JOB 建立程式TEST_PROGRAM調用P_TEST_SCHEDULER存儲過程:
begin dbms_scheduler.create_program( program_name => 'TEST_PROGRAM', program_type => 'STORED_PROCEDURE', program_action => 'p_test_scheduler', enabled => TRUE); commit;end;
建立TEST_SCHEDULERJOB2作業,調用TEST_PROGRAM程式,每小時10分時運作一次:
begin dbms_scheduler.create_job( job_name => 'test_schedulerjob2', program_name => 'TEST_PROGRAM', start_date => null, repeat_interval => 'FREQ=hourly;INTERVAL=1;byminute=10', enabled => TRUE);end;
③使用程式、排程來建立JOB 建立排程TEST_SCHEDULER指定排程周期和間隔(每天10點運作一次):
begin dbms_scheduler.create_schedule( schedule_name => 'TEST_SCHEDULER', start_date => null, repeat_interval => 'FREQ=daily;INTERVAL=1;byhour=10', end_date => null); commit;end;
建立TEST_SCHEDULERJOB3作業,根據TEST_PROGRAM程式和TEST_SCHEDULER排程來執行作業:
begin dbms_scheduler.create_job( job_name => 'test_schedulerjob3', program_name => 'TEST_PROGRAM', schedule_name => 'TEST_SCHEDULER', enabled => TRUE); commit;end;
語句執行完成,檢視USER_SCHEDULER_開頭的視圖中可以看到上述步驟建立的JOB、PROGRAM、SCHEDULER。
使用如下語句檢視USER_SCHEDULER_JOBS視圖,可以看到我們建立的三個JOB:
selectt.JOB_NAME,t.JOB_ACTION,t.ENABLED,t.START_DATE,t.PROGRAM_NAME,t.SCHEDULE_NAME,t.REPEAT_INTERVAL from user_scheduler_jobs t;
DBMS_SCHEDULER建立的JOB運作日志和詳情可以在USER_SCHEDULER_JOB_LOG和USER_SCHEDULER_JOB_RUN_DETAILS及對應的DBA開頭的視圖中查詢。DBMS_JOB沒有相關的JOB運作日志,這也是DBMS_SCHEDULER比DBMS_JOB強大的地方。
DBMS_SCHEDULER還具有建立、修改、删除、禁用JOB/SCHEDULER/PROGRAM、郵件通知等功能,其他功能請參考《DM8系統包使用手冊》。
本次分享到此結束,下周給大家介紹DM作業系統的使用方法,敬請期待。
往期回顧【幹貨分享】DM資料庫使用UTL_FILE讀寫檔案方法
【幹貨分享】DM資料庫DBMS_LOGMNR使用方法
【幹貨分享】dmfldr資料裝載使用方法