添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Oracle 定时任务

在工作中,有时候会需要定时执行存储过程或者一段sql,如果每次都人为执行,会很费力费时。所以需要使用数据库定时任务来按时执行对应sql,这样做有效的节约了时间和人力。

下面以oracle为基础,分别从oracle自带的dbms_job和dbms_scheduler两种方式来介绍定时任务的创建和执行。

一、dbms_job 方式

以下介绍定时执行存储过程,存储过程的作用是向临时表中插入每次定时执行时的日期。

  • 首先创建临时表 tmp_date ,创建语句如下:
  • create table tmp_date(test_date varchar2(20));
  • 创建存储过程 pro_date ,创建语句如下:
  • create or replace procedure proc_date as
    begin
      insert into tmp_date values (to_char(sysdate, 'yyyymmdd hh:mi:ss'));/*向测试表插入数据*/
      commit;
    
  • 创建job定时任务,实现定时自动调用存储过程。创建语句如下:
  • 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/(24
    60)' --每分钟执行
    interval => 'sysdate+1' --每天
    interval => 'sysdate+1/24' --每小时
    interval => 'sysdate+2/2460' --每2分钟
    interval => 'sysdate+30/24
    60*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');