declare
job number;
begin
DBMS_JOB.SUBMIT(
JOB => job, /*自动生成JOB_ID*/
WHAT => 'proc_date;', /*需要执行的存储过程名称或SQL语句*/
NEXT_DATE => sysdate+3/(24*60), /*初次执行时间-下一个3分钟*/
INTERVAL => 'trunc(sysdate,''mi'')+1/(24*60)' /*每隔1分钟执行一次*/
commit;
可以查询系统视图user_jobs查看创建的job定时任务,如下图。
查询临时表中数据,可以看到是按照存储过程,每分钟插入一条数据到临时表中。
DBMS_JOB.RUN(40); -- 手工调用job id 为40的任务
dbms_job.remove(40); -- 删除job id 为40的任务
dbms_job.interval(job,interval); -- 修改间隔时间
dbms_job.next_date(job,next_date); -- 修改下次执行时间
dbms_job.what(jobno,'sp_fact_charge_code;'); --修改某个job名
INTERVAL参数常用值示例
每天午夜12点 ''TRUNC(SYSDATE + 1)''
每天早上8点30分 ''TRUNC(SYSDATE + 1) + (860+30)/(2460)''
每星期二中午12点 ''NEXT_DAY(TRUNC(SYSDATE ), ''''TUESDAY'''' ) + 12/24''
每个月第一天的午夜12点 ''TRUNC(LAST_DAY(SYSDATE ) + 1)''
每个季度最后一天的晚上11点 ''TRUNC(ADD_MONTHS(SYSDATE + 2/24, 3 ), ''Q'' ) -1/24''
每星期六和日早上6点10分 ''TRUNC(LEAST(NEXT_DAY(SYSDATE, ''''SATURDAY"), NEXT_DAY(SYSDATE, "SUNDAY"))) + (6×60+10)/(24×60)''
每3秒钟执行一次 'sysdate+3/(246060)'
每2分钟执行一次 'sysdate+2/(24*60)'
:每分钟执行
Interval => TRUNC(sysdate,'mi') + 1/ (2460) --每分钟执行
interval => 'sysdate+1/(2460)' --每分钟执行
interval => 'sysdate+1' --每天
interval => 'sysdate+1/24' --每小时
interval => 'sysdate+2/2460' --每2分钟
interval => 'sysdate+30/2460*60' --每30秒
:每天定时执行
Interval => TRUNC(sysdate+1) --每天凌晨0点执行
Interval => TRUNC(sysdate+1)+1/24 --每天凌晨1点执行
Interval => TRUNC(SYSDATE+1)+(860+30)/(2460) --每天早上8点30分执行
:每周定时执行
Interval => TRUNC(next_day(sysdate,'星期一'))+1/24 --每周一凌晨1点执行
Interval => TRUNC(next_day(sysdate,1))+2/24 --每周一凌晨2点执行
:每月定时执行
Interval =>TTRUNC(LAST_DAY(SYSDATE)+1) --每月1日凌晨0点执行
Interval =>TRUNC(LAST_DAY(SYSDATE))+1+1/24 --每月1日凌晨1点执行
:每季度定时执行
Interval => TRUNC(ADD_MONTHS(SYSDATE,3),'q') --每季度的第一天凌晨0点执行
Interval => TRUNC(ADD_MONTHS(SYSDATE,3),'q') + 1/24 --每季度的第一天凌晨1点执行
Interval => TRUNC(ADD_MONTHS(SYSDATE+ 2/24,3),'q')-1/24 --每季度的最后一天的晚上11点执行
:每半年定时执行
Interval => ADD_MONTHS(trunc(sysdate,'yyyy'),6)+1/24 --每年7月1日和1月1日凌晨1点
:每年定时执行
Interval =>ADD_MONTHS(trunc(sysdate,'yyyy'),12)+1/24 --每年1月1日凌晨1点执行
二、dbms_scheduler 方式
dbms_scheduler创建定时器语法
job_name: 任务名称
job_type:定时器类型,PL/SQL Block、Stored procedure、Executable
job_action:
若job_type为存储过程,job_action为存储过程的名字;
若job_type为PL/SQL块,job_action为完整的PL/SQL代码;
若job_type为指定的外部程序,job_action为输入的script的名称或者操作系统的指令名
start_date:开始时间
repeat_interval:运行的时间间隔
end_date:到期时间
enabled:创建后自动激活
auto_drop:默认true,即当job执行完毕都到期是否直接删除job
comments:备注
repeat_interval参数实例:
FREQ:YEARLY(年) | MONTHLY(月) | WEEKLY(周) | DAILY(日) | HOURLY(时) | MINUTELY(分) | SECONDLY(秒)
BYDAY=:“MON” | “TUE” | “WED” | “THU” | “FRI” | “SAT” | “SUN”
BYMONTH: “JAN” | “FEB” | “MAR” | “APR” | “MAY” | “JUN” | “JUL” | “AUG” | “SEP” | “OCT” | “NOV” | “DEC”
以下为具体实例:
-- REPEAT_INTERVAL => 'FREQ=HOURLY; INTERVAL=1', 每小时执行一次
-- REPEAT_INTERVAL => 'FREQ=MINUTELY; INTERVAL=5', 每5分钟执行一次
-- REPEAT_INTERVAL => 'FREQ=WEEKLY; INTERVAL=1; BYDAY=MON', 每周一执行一次
-- REPEAT_INTERVAL => 'FREQ=WEEKLY; INTERVAL=1; BYDAY=MON; BYHOUR=8; BYMINUTE=00', 每周一早上8点执行一次
-- REPEAT_INTERVAL => 'FREQ=MONTHLY; INTERVAL=1; BYMONTHDAY=1; BYHOUR=8; BYMINUTE=00', 每月第一天早上8点执行一次
将上述例子改为dbms_scheduler方式,如下:
declare
job number;
v_date varchar2(20) := to_char(sysdate,'yyyymmdd hh:mi:ss');
begin
dbms_scheduler.create_job(
job_name => 'scheduler_tmpdate',-- 定时器名字
job_type => 'STORED_PROCEDURE',-- 类型:存储过程
job_action => 'proc_date', -- 存储过程名称
repeat_interval => 'FREQ=MINUTELY;interval=1', -- 定时规则,每分钟执行一次
enabled =>false -- 创建后不激活
dbms_scheduler.enable('scheduler_tmpdate'); -- 激活
dbms_scheduler.run_job('scheduler_tmpdate'); -- 运行job
dbms_scheduler.run_job(jobName) – 运行job
dbms_scheduler.stop_job(jobName,force) 停止job,force默认为false
dbms_scheduler.drop_job(jobName) 删除job
dbms_scheduler.enable(jobName) 打开job
dbms_scheduler.disable(jobName,force) 禁用job,force参数用于dependencies
相关系统视图
user_scheduler_jobs 查看所有job信息
user_scheduler_running_jobs 查看所有正在运行的job
user_scheduler_job_run_details job运行日志
User_Scheduler_Job_Log job job日志
!注意事项:
dbms_scheduler创建job需要创建权限,否则创建时会出错,grant create job to xxx
,可以通过该命令将权限赋值给指定用户。
三、带参数的存储过程的定时任务创建
上述给的例子是没有参数传入的,但在工作中,有时候会有动态参数需要传入,这时就需要在上述两种方式中修改部分内容,主要修改内容如下。
dbms_job 带参数传入的定时任务
使用dbms_job创建定时任务时,如果存储过程有参数传入,可以将原先存储过程名称改为具体的执行sql语句块,在语句块中进行参数的传递,最终达到参数传递的效果。
declare
job number;
BEGIN
DBMS_JOB.SUBMIT(
JOB => job, /*自动生成JOB_ID*/
WHAT => 'declare
i_date varchar2(8) := to_char(sysdate,''yyyymmdd'');
BEGIN
proc_date(i_date);
commit;
end;', /*需要执行的存储过程名称或SQL语句*/
NEXT_DATE => sysdate+1/(24*60), /*初次执行时间-下一个1分钟*/
INTERVAL => 'trunc(sysdate,''mi'')+1/(24*60)', /*每隔1分钟执行一次*/
no_parse => false
commit;
dbms_scheduler带参数传入的定时任务
使用dbms_scheduler创建带参数传入的定时任务时,可以利用具体语句进行参数项配置,最后运行定时任务,具体内容如下,在原来的基础上增加number_of_arguments => 1,
参数个数配置,dbms_scheduler.set_job_argument_value
设置参数值的配置。如果存在多个参数值,则需要配置多个dbms_scheduler.set_job_argument_value
,里面的参数索引需要按照实际的位置进行改变。
declare
job number;
v_date varchar2(20) := to_char(sysdate,'yyyymmdd hh:mi:ss');
begin
dbms_scheduler.create_job(
job_name => 'job_date',
job_type => 'STORED_PROCEDURE',
job_action => 'proc_date',
number_of_arguments => 1,
repeat_interval => 'FREQ=MINUTELY;interval=1',
enabled =>false
dbms_scheduler.set_job_argument_value(
job_name => 'job_date',
argument_position => 1,
argument_value => v_date
dbms_scheduler.enable('job_date');
dbms_scheduler.run_job('job_date');
多个参数:
declare
job number;
v_date varchar2(20) := to_char(sysdate,'yyyymmdd hh:mi:ss');
begin
dbms_scheduler.create_job(
job_name => 'job_date',
job_type => 'STORED_PROCEDURE',
job_action => 'proc_date',
number_of_arguments => 1,
repeat_interval => 'FREQ=MINUTELY;interval=1',
enabled =>false
dbms_scheduler.set_job_argument_value(
job_name => 'job_date',
argument_position => 1,
argument_value => v_date
dbms_scheduler.set_job_argument_value(
job_name => 'job_date',
argument_position => 2,
argument_value => 'hcx'
dbms_scheduler.enable('job_date');
dbms_scheduler.run_job('job_date');