创建对应的包,以方便触发调用
/*包声明*/
CREATE OR REPLACE PACKAGE yjb.pkg_scene_job AS /*创建同步任务*/FUNCTION F_SYNC_DRUG_STOCK RETURN NUMBER;/*同步*/PROCEDURE PRC_SYNC_DRUG_STOCK(RUNJOB VARCHAR2) ;
END pkg_scene_job;
/*包体*/
CREATE OR REPLACE PACKAGE body yjb.pkg_scene_job AS /*创建任务*/FUNCTION F_SYNC_DRUG_STOCK RETURN NUMBER AS/*同步*/pragma autonomous_transaction;sync_stock_sql varchar2(3000);V_JOB_NAME varchar2(50):='SYNC_DRUG_STOCK_JOB';--JOB任务名称SYNC_DRUG_STOCK_JOBCNT NUMBER:=0;JOBEXETIME NUMBER:=0 ;--任务执行时间(分钟)plsqlblk varchar2(800);BEGINBEGINSELECT count(1) INTO SYNC_DRUG_STOCK_JOBCNT FROM user_scheduler_jobs a WHERE a.JOB_NAME=V_JOB_NAME;IF SYNC_DRUG_STOCK_JOBCNT =1 THENSELECT to_number((SYSDATE - a.START_DATE)*24*60) INTO JOBEXETIME FROM user_scheduler_jobs a WHERE a.JOB_NAME=V_JOB_NAME;/*如果任务执行时间超过20分钟 则将任务删除*/IF JOBEXETIME >=20 THEN-- sys.dbms_scheduler.drop_job();-- 特别说明: force => false -- false:job 执行完成后再删除 -- true :立即删除(job 未必执行完成哦)sys.dbms_scheduler.drop_job(job_name => V_JOB_NAME,force => true);ELSE RETURN 1;END IF;END IF;plsqlblk:='begin pkg_scene_job.PRC_SYNC_DRUG_STOCK(' ||chr(39)|| V_JOB_NAME ||chr(39)|| '); end;';sys.dbms_scheduler.create_job(job_name => V_JOB_NAME,job_type => 'PLSQL_Block',job_action => plsqlblk,number_of_arguments =>0,start_date => SYSDATE,repeat_interval => NULL,end_date => NULL,job_class => 'DEFAULT_JOB_CLASS',enabled => TRUE,auto_drop => TRUE,comments => '同步数据',credential_name => null,destination_name => NULL);END;COMMIT;RETURN 1;EXCEPTION WHEN OTHERS thenRETURN 0; END F_SYNC_DRUG_STOCK;/*同步表数据(全量/增量)数据量上万时 建议将数据量拆分进行*/PROCEDURE PRC_SYNC_DRUG_STOCK(RUNJOB VARCHAR2) ISpragma autonomous_transaction;BEGIN-- SYS.DBMS_LOCK.SLEEP(10);-- EXECUTE IMMEDIATE INBLOCK;merge into table1 vusing (SELECTi1.HOSPITAL_AREA,i1.DRUG_CODE,i1.AMOUNT_PER_PACKAGE,i1.PACKAGE_UNITS_CODE,i1.FIRM_ID,i1.STORAGE,i1.ITEM_PRICE,i1.QUANTITY,i1.AVAILABLE_STORAGE,i1.SUPPLY_INDICATOR,i1.DRUG_SPECFROMtable2@interface i1) don (v.HOSPITAL_AREA = d.HOSPITAL_AREA AND v.DRUG_CODE=d.DRUG_CODE AND v.STORAGE=d.STORAGE) -- 这里通过主键判断,数据是否存在when matched thenupdate set v.QUANTITY = d.QUANTITY,v.AVAILABLE_STORAGE = d.AVAILABLE_STORAGEwhen not matched theninsert (v.HOSPITAL_AREA,v.DRUG_CODE,v.AMOUNT_PER_PACKAGE,v.PACKAGE_UNITS_CODE,v.FIRM_ID,v.STORAGE,v.ITEM_PRICE,v.QUANTITY,v.AVAILABLE_STORAGE,v.SUPPLY_INDICATOR,v.DRUG_SPEC)values (d.HOSPITAL_AREA,d.DRUG_CODE,d.AMOUNT_PER_PACKAGE,d.PACKAGE_UNITS_CODE,d.FIRM_ID,d.STORAGE,d.ITEM_PRICE,d.QUANTITY,d.AVAILABLE_STORAGE,d.SUPPLY_INDICATOR,d.DRUG_SPEC) ;-- DBMS_OUTPUT.PUT_LINE('===========执行' || INBLOCK || '成功=============');SYS.DBMS_SCHEDULER.SET_ATTRIBUTE(NAME => RUNJOB,ATTRIBUTE => 'auto_drop',VALUE => TRUE);--SYS.DBMS_SCHEDULER.DISABLE(NAME => RUNJOB);COMMIT;EXECUTE immediate 'ALTER SESSION CLOSE DATABASE link hisinterface' ;END PRC_SYNC_DRUG_STOCK;
END pkg_scene_job;
触发同步任务:
SELECT yjb.pkg_scene_job.F_SYNC_DRUG_STOCK() AS a FROM dual WHERE 1=0;
没有结果行时是不会触发的,以下方式可触发:
SELECT yjb.pkg_scene_job.F_SYNC_DRUG_STOCK() AS a FROM dual;
PS:一定是使用(调用)到 触发函数yjb.pkg_scene_job.F_SYNC_DRUG_STOCK(),才可完成触发。如:
/*无法触发情况*/
with t1 as (select 1 as a,unicorn.pkg_scene_job.F_SYNC_DRUG_STOCK() as f from dual)
select a from t1
; /*可触发情况*/with t1 as (select 1 as a,unicorn.pkg_scene_job.F_SYNC_DRUG_STOCK() as f from dual)
select f from t1
;
或
with t1 as (select 1 as a,unicorn.pkg_scene_job.F_SYNC_DRUG_STOCK() as f from dual)
select a from t1 where f=1
;
查看后台任务:
SELECT * FROM user_scheduler_jobs;
查看后台任务日志:
SELECT * FROM user_scheduler_job_run_details a WHERE instr(a.job_name,'SYNC_DRUG_STOCK_JOB')>=1 ORDER BY a.log_date DESC;