1.1 简述
oracle 10g 的dbms_scheduler强大是强大,就是复杂了些,而9i的dbms_job包又简单了些.
一些基本的东西就不说了,oracle文档有,很多网友也有.这里需要补充的是如何更好的使用这个包裹.
按照我个人的意见,建立一个Job之前需要大张旗鼓的执行创建program和scheduler一般不是很有必要,除非您的任务的计划时间比较多样话.我个人对于一些比较简单的JOB,通常都是直接的用这个报create_job就完事了.
对于程序员或者DBA,我不再建议初学者继续使用DBMS_JOB包,盖因为ORACLE公司以后很可能不再维护这个包,甚至这个包会在更高的版本上消失.
1.2 概念
老美的东西必须适当的翻译到国文,或者概念混淆对于学习还是很不利的.
PROGRAM --程序 ,可以执行的job实体.
scheduler --计划 ,或者是时间表,就是安排什么时候做事情的时间表.
JOB --任务 ,整体的一件事情,包括要干什么,以及时间如何安排.
做一件事情,首先得告诉别人要干什么,这个干什么就是program,然后要告诉别人如何安排时间反复的或者单次的干,那么这个安排就是属于时间表,整体合起来就是一个任务了.
例如,作为DBA,你想每周五的晚上23:00的时候执行表格数据的重新统计,那么你就可以先建议一个关于数据统计的程序,然后再安排一个时间表(每周五的晚上23:00),并把前二者关联起来,就创建了一个任务.
所以,JOB包含SCHEDULER和PROGRAM .
作为create_job这个过程
1.3 关于interval 的scheduler calender语法(或者是日历语法)的总结
这里的总结是来自后面的附录。
a)关键格式
part1 FREQ=[SECONDLY| MINUTELY| HOURLY| DAILY| WEEKLY| MONTHLY| YEARLY]
part2 [INTERVAL=n] n必须大于0的整数。
part3 [EXCULUDE|INCLUDE] ,通常更一个已经创建好的schedule
part4 [BYDAY| BYMONTHDAY| BYMONTH| BYDATE| BYHOUR| BYMINUTE |BYSECOND]=?
part5 [BYSETPOS=n] ,n可以是负数也可以是整数。
part6 PERIODS=N ;BYPERIOD=[N|1,2,3,N];
FREQ 是必须的,interval是可选的,如果不输入,就是按照后面byXXX的处理。PART4也是必须的。
part5部分也是可选的。
b)part4 中值的格式,以及各个特异点。
BYSECOND=[N|N1,N2,N3..,|-N] ,就是说可以是单独的值,也可以是用逗号隔开的值列表。
例如可以是 bysecond=1 表示在第一秒。bysecond=-1 表示最后一秒.
bysecond=1,11,21,31,41,51 .表示在第1秒,第11秒...发生。
BYDAY= [N|N1,N2,N3..|XN|-XN] ,但是N必须是MON,TUE,WED,TUE,FRI,SAT,SUN
X必须是自然数,例如FREQ=MONTHLY,BYDAY=2FRI,表示第二个星期五。
FREQ=YEARLY,BYDAY=-1FRI ,表示每年的最后一个星期五.
BYMONTHDAY= [N|N1,N2,N3..| -N] ,N必须是1~31的自然数,前面两种格式同上面。第三中表示的是倒数
第n天, 例如bymonthday=-1 表示的是每个月的最后一天,就这样就可以避开不规则的月份
BYMONTH= [N|N1,N2,N3..] N= JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC
BYHOUR ,BYMINUTE 同 BYSECOND,同样支持N和-N,以及列表
BYDATE =[YYYYMMDD|YYYYMMDD[+|-|^]SPAN:N[D|W]]
这是比较复杂的格式.YYYY可以不要.
SPAN表示延伸,如果是+,则表示后面,-表示之前,^表示前后(包括了+,-).
D是天,W是周.但是都要包含自身.
BYSETPOS =[N|-N] ,但只有和FREQ=[MONTHLY|YEARLY]配对.
PERIODS和BYPERIOD ,已经做过测试,但是没有看到实际的效果.
1.4 语法检测
DECLARE
L_start_date TIMESTAMP; --开始日期
l_next_date TIMESTAMP; --上一次执行的时间
l_return_date TIMESTAMP;--下一次执行的时间 ,就是l_next_date的下一次.
begin
l_start_date := trunc(SYSTIMESTAMP);
l_return_date := l_start_date;
for ctr in 1..10 loop
dbms_scheduler.evaluate_calendar_string(
'FREQ=YEARLY; BYDATE=1014^SPAN:1W',l_start_date, l_return_date, l_next_date);
dbms_output.put_line('Next Run on: ' ||to_char(l_next_date,'yyyymmdd hh24:mi:ss'));
l_return_date := l_next_date;
end loop;
end;
第一个参数不用说了,第二个也一目了然.第三个表示第一次输出的下次执行时间,而第四个表示下一个执行时间之后的下一次时间. 因为只有通过第三个参数,这个过程才能知道上次执行的时间是什么,从而判断下次的执行时间.
有了这个过程,您就可以检测一下自己编写的过程是否正了.