oracle中job定时调用存储过程的实例

时间:2023-03-08 16:05:31
oracle中job定时调用存储过程的实例

使用job模拟定时从元数据表中抽取指定数据进入目标表的过程。

一、创建元数据表

  --create table test_origianl

  

  create table test_original_data(
    id number(10,2) primary key,
    name varchar2(200),
    descCont varchar2(100),
    dateType char(5)

  );

二、元数据表中插入数据

  

  insert into test_original_data values(2.9,'name1','desc1','int');
  insert into test_original_data values(3.0,'name2','desc2','long');
  insert into test_original_data values(2.8,'name3','desc3','float');
  insert into test_original_data values(2.6,'name4','desc4','do');
  insert into test_original_data values(2.1,'name223','desc33','float');
  insert into test_original_data values(5.12,'name22r34','desc3r34','float');

三、提交事务

  commit;

四、创建目标表

  ---create table

  为保持与元数据表相同的表结构,使得元数据表中的记录可以不做任何修改直接插入目标表中,采用CTAS的方式创建目标表。

  

  create table test_destination_dat
  as
    select * from test_original_data where 1!=1;

  只创建相同的表结构,不导入元数据表中的记录。

五、提交事务

  commit;

六、创建定时被调用的存储过程

  ---- create procedure

  

  create or replace procedure job_test_pro
    authid current_user
  as
  begin

    --先truncate table清空原来的数据,重新把符号条件的数据导入(此处使用truncate在大数据量的情况下戏剧化的提高效率)
    execute immediate 'truncate table test_destination_dat';
    insert into test_destination_dat (select * from test_original_data where dateType='float' );
  exception
    when others then
    dbms_output.put_line('errorMsg'||SQLERRM||'errorCode'||SQLCODE);
  end job_test_pro;

  注:1、在存储过程中一般是没有create table 、truncate table的权限的。如果在存储过程中直接使用语句truncate table test_destination_dat会报错,不能执行该语      句。 在存储过程一般是不能直接使用create table,truncate table这类似的语句的,如果要使用这些语句必须使用excute immediate + 所要执行的sql语句来实现。

    2、Authid Current_User:

      这个语句比较重要,如果我们在创建存储过程的时候不添加这条语句执行该存储过程将不会成功,原因是默认情况存储过程是没有Create table,truncate table等       权限的,即使当前用户有DBA的权限也不行,如果存储过程中存在创建表、截断表的操作,可以有以下两种方式来解决该问题。

      (1) 显示的赋予该用户Create table的权限,grant create table to user.
      (2) 在存储过程中使用Authid Current_User 标识使用当前用户的权限。

七、创建job

  1、定义job名称

    variable job2014 number   ---定义在oracle中自动生成job的序号的数据类型对应到dba_jobs的数据字典中的字段job的值。现在job值为41对应名称为job2014数     据类型为number

  2、将job注册到dba_jobs表中定时启动job调用存储过程

    begin

      dbms_job.submit(:job2014,'JOB_TEST_PRO;',sysdate,'sysdate+1/1440');

    end;

    /

    commit;

    注意:dbms_job.submit()方法的定义如下

             sys.dbms_job.submit(job => :jobno,
what => 'myProc;myProcs;myProcss(''测试'');',//用分号将多个存储过程分开,有参数的话直接写就可以了
next_date => to_date('07-04-2011 22:00:00', 'dd-mm-yyyy hh24:mi:ss'),
interval => 'sysdate+1');
        1、这里需要注意的是,在submit方法的前面一定要先定义job这个变量
       2、submit方法的第二个参数是一个存储过程的名,记得在后面添加“;”号
       3、在next_date是一个时间类型变量而不是一个字符串,所以需要注意不要把它当成字符串,不需要对该参数加引号
       4、最后一个参数interval是一个字符串类型,记得添加引号
       5、第一个参数格式为:jobno,目的是绑定job和存储过程。
       6、最常见的错误如下所示:ORA-01008: not all variables bound就是没有定义变量的意思。一定记的在使用submit方法时定义jobno变量。
       7、下面是常有的设置Interval的方法:
            每天固定时间运行,比如早上8点:Trunc(Sysdate+1) + 8/24
            每天:trunc(sysdate+1)
            每周:trunc(sysdate+7)
            每月:trunc(sysdate+30)
            每个星期日:next_day(trunc(sysdate),’SUNDAY’)
            每天6点:trunc(sysdate+1)+6/24
            半个小时:sysdate+30/1440
        8、声明变量和绑定job变量到存储过程并注册到dba_jobs表中必须在sqlplus下执行,在plsqldevloper中不能成功运行。
八、job异常情况处理
   JOB不能运行情况处理
    1.先来了解一下JOB的参数说明:与job相关的参数一个是job_queue_processes,这个是运行JOB时候所起的进程数,当然系统里面JOB大于这个数值后,就会有排     队等候的,最小值是0,表示不运行JOB,最大值是36,在OS上对应的进程时SNPn,9i以后OS上管理JOB的进程叫CJQn.可以使用下面这个SQL确定目前有几个SNP/C     JQ在运行。
     select * from v$bgprocess,这个paddr不为空的snp/cjq进程就是目前空闲的进程,有的表示正在工作的进程。
     另外一个是job_queue_interval,范围在1——3600之间,单位是秒,这个是唤醒JOB的process,因为每次snp运行完他就休息了,需要定期唤醒他,这个值不能     太小,太小会影响数据库的性能。
    2.诊断:先确定上面这两个参数设置是否正确,特别是第一个参数,设置为0了,所有JOB就不会跑,确认无误后,我们继续向下。
    3.使用下面的SQL察看JOB的的broken,last_date和next_date,last_date是指最近一次job运行成功的结束时间,next_date是根据设置的频率计算的下次执行     时间,根据这个信息就可以判断JOB上次是否正常,还可以判断下次的时间对不对,SQL如下:
     select * from dba_jobs
     有时候我们发现他的next_date是4000年1月1日,说明job要不就是在running,要不就是状态是break(broken=Y),如果发现JOB的broken值为Y,找用户了解     一下,确定该JOB是否可以broken,如果不能broken,那就把broken值修改成N,修改再使用上面的SQL察看就发现他的last_date已经变了,JOB即可正常运行,     修改broken状态的SQL如下:
      declare
      BEGIN
        DBMS_JOB.BROKEN(<JOB_ID>,FALSE);
      END;
    4.使用下面的SQL查询是否JOB还在Running
      select * from dba_jobs_running
     如果发现JOB已经Run了很久了还没有结束,就要查原因了。一般的JOB running时会锁定相关的相关的资源,可以查看一下v$access和v$locked_object这两个v     iew,如果发现其他进程锁定了与JOB相关的Object,包括PKG/Function/Procedure/Table等资源,那么就要把其他进程删除,有必要的话,把JOB的进程也删除     ,再重新跑看看结果。
    5.如果上面都正常,但是JOB还不run,怎么办?那我们要考虑把JOB进程重启一次,防止是SNP进程死了造成JOB不跑,指令如下:
      alter system set job_queue_processes=0 ——关闭job进程,等待5——10秒钟
      alter system set job_quene_processes=5 ——恢复原来的值
九、手动运行job的指令
  begin
    dbms_job.run(:job2014);
  end;
  /
十、删除job
  begin
    dbms_job.remove(:job2014);
  end;
  /
十一、查看job相关视图及各字段的注解
  

  select job,last_date,last_sec,broken,failures,interval, what from dba_jobs


  详解 dba_jobs中几个比较重要的字段


  job: 指的是job的id号。比如上面的 41


  failures:job执行的时候失败次数,如果超过了15次,那么broken列将被标为Y,以后就不会运行该job了


  broken:默认为N,如果为Y,意味着不再执行该job!


  interval:执行job的间隔时间。


  what:该job的实际工作。

  总结:模拟定时从元数据表中抽取指定类型的数据添加到目标表中,用定时job调用存储过程。