drop table ma_schedue_task ;

---test_task(:1,:2)
create table ma_schedue_task(
created_by varchar2(100) default 'system' not null,
created_date date default sysdate not null,
updated_by varchar2(100) default 'system' not null,
updated_date date default sysdate not null,
id_ma_schedue_task varchar2(32) default sys_guid() not null,
procedure_name varchar2(100),
task_months number default 0 not null,
task_days number default 0 not null,
task_hours number default 0 not null ,
task_minutes number default 0 not null,
first_time date ,
prev_time date,
next_time date,
is_effected varchar2(2) default 'N' not null,
has_param varchar2(2) default 'N' not null,
thread_num number default 1 not null,
task_priority number default 100 not null
);
comment on table ma_schedue_task is '任务配置表'; comment on column ma_schedue_task.created_by is '创建人'; comment on column ma_schedue_task.created_date is '创建时间'; comment on column ma_schedue_task.updated_by is '更新人'; comment on column ma_schedue_task.updated_date is '更新时间'; comment on column ma_schedue_task.id_ma_schedue_task is '主键'; comment on column ma_schedue_task.procedure_name is '过程名,可带参数'; comment on column ma_schedue_task.task_months is '频率:月'; comment on column ma_schedue_task.task_days is '频率:天'; comment on column ma_schedue_task.task_hours is '频率:时'; comment on column ma_schedue_task.task_minutes is '频率:分钟'; comment on column ma_schedue_task.first_time is '首次执行时间'; comment on column ma_schedue_task.prev_time is '上次执行时间'; comment on column ma_schedue_task.next_time is '下次执行时间'; comment on column ma_schedue_task.is_effected is '是否生效:N-否,Y-是'; comment on column ma_schedue_task.has_param is '是否带有入参:N-否,Y-是'; comment on column ma_schedue_task.thread_num is '线程数'; comment on column ma_schedue_task.task_priority is '优先级'; create index idx_id_ma_schedue_task on ma_schedue_task(id_ma_schedue_task) initrans 16; alter table ma_schedue_task add constraint pk_id_ma_schedue_task primary key(id_ma_schedue_task) using index idx_id_ma_schedue_task; drop table ma_schedue_param ; create table ma_schedue_param(
created_by varchar2(100) default 'system' not null,
created_date date default sysdate not null,
updated_by varchar2(100) default 'system' not null,
updated_date date default sysdate not null,
id_ma_schedue_param varchar2(32) default sys_guid() not null,
id_ma_schedue_task varchar2(32),
param_order number,
param_value varchar2(100),
param_group number,
run_status varchar2(2) );
comment on table ma_schedue_param is '任务配置表'; comment on column ma_schedue_param.created_by is '创建人'; comment on column ma_schedue_param.created_date is '创建时间'; comment on column ma_schedue_param.updated_by is '更新人'; comment on column ma_schedue_param.updated_date is '更新时间'; comment on column ma_schedue_param.id_ma_schedue_param is '主键'; comment on column ma_schedue_param.id_ma_schedue_task is '关联任务表ID'; comment on column ma_schedue_param.param_order is '参数顺序'; comment on column ma_schedue_param.param_value is '参数值'; comment on column ma_schedue_param.param_group is '参数组别,指定那些参数是一起执行的'; comment on column ma_schedue_param.run_status is '状态:W-等待执行,R-执行中,E-执行失败,S-执行成功'; create index idx_id_ma_schedue_param on ma_schedue_param(id_ma_schedue_param) initrans 16; alter table ma_schedue_param add constraint pk_id_ma_schedue_param primary key(id_ma_schedue_param) using index idx_id_ma_schedue_param;

测试

--测试不含参数的类型
create or replace procedure test_task is begin
dbms_output.put_line('hi,test_task');
end test_task; DELETE FROM MA_SCHEDUE_TASK WHERE 1=1;
insert into ma_schedue_task(procedure_name,task_days,first_time,has_param,thread_num,is_effected)
values('test_task',1,sysdate-2/24,'N',1,'Y');
COMMIT; DELETE FROM MA_SCHEDUE_TASK WHERE 1=1;
insert into ma_schedue_task(procedure_name,task_months,first_time,has_param,thread_num,is_effected)
values('test_task',1,sysdate-2/24,'N',1,'Y');
COMMIT; DELETE FROM MA_SCHEDUE_TASK WHERE 1=1;
insert into ma_schedue_task(procedure_name,Task_Hours,first_time,has_param,thread_num,is_effected)
values('test_task',1,sysdate-2/24,'N',1,'Y');
COMMIT; DELETE FROM MA_SCHEDUE_TASK WHERE 1=1;
insert into ma_schedue_task(procedure_name,Task_Minutes,first_time,has_param,thread_num,is_effected)
values('test_task',30,sysdate-2/24,'N',1,'Y');
COMMIT; --测试含了入参的类型
create or replace procedure test_task_param(i_name in varchar2,i_point in varchar2) is begin
dbms_output.put_line(i_name||'积分'||i_point);
end test_task_param; declare
v_task_id varchar2(32);
begin --select sys_guid() into v_task_id ;
delete from ma_schedue_task;
delete from ma_schedue_param; insert into ma_schedue_task
(procedure_name,
task_days,
first_time,
has_param,
thread_num,
is_effected)
values
('test_task_param(:1,:2)', 1, sysdate - 2 / 24, 'Y', 1, 'Y')
returning ID_MA_SCHEDUE_TASK into v_task_id; insert into ma_schedue_param
(id_ma_schedue_task, param_order, param_value, param_group, run_status)
values
(v_task_id, 1, '乱世佳人', 1, 'W'); insert into ma_schedue_param
(id_ma_schedue_task, param_order, param_value, param_group, run_status)
values
(v_task_id, 2, '', 1, 'W');
end;
/ select * from ma_schedue_task;
select * from ma_schedue_param; declare
begin
pkg_schedue_task.dispatch_task; end;
/ select * from ma_error_log

任务调度

--grant DEBUG CONNECT SESSION to scott;   sys;change_on_install as sysdba
create or replace package pkg_schedue_task is procedure scan_task(i_current_time in date,o_ref out sys_refcursor);
procedure exec_task( i_task_id in varchar2);
procedure dispatch_task;
procedure add_task (i_record in ma_schedue_task %rowtype); --配置无参数的方法
procedure add_task (i_record in ma_schedue_task %rowtype,i_param in ma_schedue_param %rowtype); --配置带参数的方法 end pkg_schedue_task;
/ create or replace package body pkg_schedue_task is procedure dispatch_task is v_ref sys_refcursor;
v_task ma_utils.ma_task_record;
begin
scan_task(sysdate, v_ref);
loop
fetch v_ref
into v_task;
exit when v_ref%notfound;
exec_task(v_task.task_id);
end loop;
close v_ref;
end dispatch_task; --扫描需要执行的任务 procedure scan_task(i_current_time date, o_ref out sys_refcursor) is begin open o_ref for
select t.id_ma_schedue_task, t.thread_num
from ma_schedue_task t
where t.is_effected = 'Y'
and ((t.first_time <= i_current_time and t.next_time is null) or
(t.next_time is not null and t.next_time <= i_current_time))
order by t.task_priority asc; end scan_task;
--执行任务
procedure exec_task(i_task_id in varchar2) is v_task ma_schedue_task%rowtype;
v_no_task_exp exception;
v_task_no_param_exp exception;
ls_pn varchar2(1000) := 'pkg_schedue_task.exec_task';
v_current_time date;
v_next_time date;
v_group ma_schedue_param.param_group%type;
v_sql varchar2(4000);
v_cur number;
v_result number;
begin <<get_task>>
begin
--获取任务信息
select *
into v_task
from ma_schedue_task r
where r.id_ma_schedue_task = i_task_id
and r.is_effected = 'Y'
and rownum =1;
exception
when no_data_found then
raise v_no_task_exp;
end get_task;
--获取任务下次执行时间,如果是第一次执行,则去初次执行时间
select decode(v_task.next_time,
null,
v_task.first_time,
v_task.next_time)
into v_current_time
from dual;
--根据设置的频度修改下次执行时间
v_next_time := v_current_time + v_task.TASK_MINUTES / (24 * 60) +
v_task.TASK_hours / 24 + v_task.TASK_DAYS;
v_next_time := add_months(v_next_time, v_task.task_months); update ma_schedue_task t
set t.next_time = v_next_time, t.prev_time = sysdate
where t.id_ma_schedue_task = i_task_id;
commit;
--如果任务不带参数,则直接过程,但此处存在SQL注入的可能
if v_task.has_param = 'N' then
ma_utils.exec_plsql_block(v_task.PROCEDURE_NAME);
return;
end if ;
--获取处于等待状态的最小参数分组值
select min(r.param_group)
into v_group
from ma_schedue_param r
where r.id_ma_schedue_task = i_task_id
and r.run_status = 'W';
if v_group is null then
raise v_task_no_param_exp;
end if;
update ma_schedue_param r
set r.run_status = 'R'
where r.id_ma_schedue_task = i_task_id
and r.param_group = v_group
and r.run_status = 'W';
commit; v_sql := ' begin ' || rtrim(v_task.procedure_name, ';') || ';end;'; v_cur := dbms_sql.open_cursor;
dbms_sql.parse(v_cur, v_sql, dbms_sql.native);
--绑定参数
for param in (select r.param_order, r.param_value
from ma_schedue_param r
where r.id_ma_schedue_task = i_task_id
and r.param_group = v_group
and r.run_status = 'R'
order by param_order) loop
dbms_sql.bind_variable(v_cur,
':' || param.param_order,
param.param_value);
end loop;
v_result := dbms_sql.execute(v_cur);
dbms_sql.close_cursor(v_cur); update ma_schedue_param r
set r.run_status = 'S'
where r.id_ma_schedue_task = i_task_id
and r.param_group = v_group
and r.run_status = 'R';
commit; exception
when v_no_task_exp then
ma_utils.add_error_log(ls_pn, i_task_id || '任务不存在', 'INFO');
when v_task_no_param_exp then
ma_utils.add_error_log(ls_pn,
i_task_id || '任务没有配置实参值',
'ERROR');
when others then
update ma_schedue_param r
set r.run_status = 'E'
where r.id_ma_schedue_task = i_task_id
and r.param_group = v_group
and r.run_status = 'R';
commit;
ma_utils.add_error_log(ls_pn,
i_task_id || substr(sqlerrm, 1, 300),
'ERROR');
end exec_task; end pkg_schedue_task;
/

错误日志

drop table ma_error_log ;
---错误日志表
create table ma_error_log(
created_by varchar2(100) default 'system' not null,
created_date date default sysdate not null,
updated_by varchar2(100) default 'system' not null,
updated_date date default sysdate not null,
id_ma_error_log varchar2(32) default sys_guid() not null,
procedure_name varchar2(100),
error_msg varchar2(2500),
error_level varchar2(30)
);
comment on table ma_error_log is '任务配置表'; comment on column ma_error_log.created_by is '创建人'; comment on column ma_error_log.created_date is '创建时间'; comment on column ma_error_log.updated_by is '更新人'; comment on column ma_error_log.updated_date is '更新时间'; comment on column ma_error_log.id_ma_error_log is '主键'; comment on column ma_error_log.procedure_name is '发生异常时调用的方法'; comment on column ma_error_log.error_msg is '错误信息'; comment on column ma_error_log.error_level is '错误级别:info,important,error'; create index idx_id_ma_error_log on ma_error_log(id_ma_error_log) initrans 16;
create index idx_error_created_date on ma_error_log(created_date) initrans 16; alter table ma_error_log add constraint pk_id_ma_error_log primary key(id_ma_error_log) using index idx_id_ma_error_log; --创建工具包
create or replace package ma_utils is type ma_task_record is record(task_id varchar2(32),thread_num number); procedure add_error_log(i_procedure_name in varchar2,
i_error_msg in varchar2,
i_error_level in varchar2); procedure exec_plsql_block(i_plsql in varchar2); end ma_utils;
/ create or replace package body ma_utils is procedure add_error_log(i_procedure_name in varchar2,
i_error_msg in varchar2,
i_error_level in varchar2) is
pragma autonomous_transaction;
begin insert into ma_error_log
(procedure_name, error_msg, error_level)
values
(i_procedure_name, i_error_msg, i_error_level); commit;
exception
when others then
rollback; end add_error_log; procedure exec_plsql_block(i_plsql in varchar2) is
begin
execute immediate 'begin ' || rtrim(i_plsql, ';') || ' ; end ;';
end exec_plsql_block; end ma_utils;
/

PL/SQL 训练07--发现问题的更多相关文章

  1. PL/SQL 训练03 --异常

    --程序员在开发的时候,经常天真的认为这个世界是完美的,用户如同自己般聪明,总能按照自己设想的方式--操作系统输入数据.但残酷的事实告诉我们,这是不可能的事情,用户总会跟我们相反的方式操作系统--于是 ...

  2. PL/SQL 训练13--plsql 优化

    --数据缓存技术 --PGA和SGA---SGA:系统全局区域--PGA:Process Global Area是为每个连接到Oracle的用户进程保留的内存. ---PLSQL从PGA获取信息的速度 ...

  3. PL/SQL 训练12--动态sql和绑定变量

    --什么是动态SQL?动态PL/SQL--动态SQL是指在运行时刻才构建执行的SQL语句--动态PL/SQL是指整个PL/SQL代码块都是动态构建,然后再编译执行 --动态SQL来可以用来干什么? - ...

  4. PL/SQL 训练11--包

    --所谓包,就是把一组PL/SQL的代码元素组织在一个命名空间下.--一种可以把程序或者其他的PL/SQL元素比如游标.类型.变量的组织结构在一起的结构(包括逻辑结构和物理结构)--包提供了非常重要的 ...

  5. PL/SQL 训练10--io及文件操作

    多数程序只需要通过SQL和底层数据库进行交互--有些情况,不可避免的还是会有一些场景,需要从PL/SQL给外部环境发送信息--或是从一些外部的源读入信息 --这节课介绍下面这些内置包 dbms_out ...

  6. PL/SQL 训练08--触发器

    --什么是触发器呢?--一触即发,某个事件发生时,执行的程序块?--数据库触发器是一个当数据库发生某种事件时作为对这个事件的响应而执行的一个被命名的程序单元 --适合场景--对表的修改做验证--数据库 ...

  7. PL/SQL 训练05--游标

    --隐式游标--通过一个简单的SELECT ...INTO 语句提取一行数据,并放在一个局部变量中,最简单获取数据的途径 --显示游标--可以在声明单元明确的声明一个查询,这样可以在一个或多个程序中打 ...

  8. PL/SQL 训练04--事务

    --pl/sql通过SQL和ORACLE数据库紧密的整合在一起--在pl/sql中可以执行任何操作语句(DML语句),包括INSERT,UPDATE,DELETE,MERGE,也包括查询语句--可否执 ...

  9. PL/SQL 训练02--集合数组

    1. 请列举关联数组.嵌套表.VARRAY三种集合类型的区别区别:1 关联数组只能在plsql中使用,嵌套表,varray可用于sql中,数据库表中的列2 嵌套表,varray必须在使用的时候初始化, ...

  10. PL/SQL 训练01--基础介绍

    --开始介绍变量之前,我们先看下怎么在PLSQL写程序,如下我们写了一个块 declare --声明部分,声明变量 v_name ) :='hello world'; begin --执行区域 dbm ...

随机推荐

  1. 如果在applicationContext.xml中没有配置bean的属性,那么也会导致空指针异常

    报错如下: java.lang.NullPointerException cn.itcast.action.VisitAction.toAddPage(VisitAction.java:37) sun ...

  2. struts2提交文件时,出现页面重置又无法返回input现象,我没有解决这个问题

    查看资料得知,是因为我使用的tomcat是8的原因,调整到6就可以了.但我没有改变Tomcat的版本,不知道该怎么解决这个问题.

  3. 《JavaScript高级程序设计》第7章 函数表达式

    定义函数的方式有两种:函数声明和函数表达式 // 函数声明 function function_name(argument) { // body... } // 函数表达式 var function_ ...

  4. 《JavaScript高级程序设计》第6章补充 继承

    基于原型链继承 将父类的实例赋给子类的prototype来实现继承. 原理:父类的实例有父类所有的实例属性和原型方法,将它赋给子类的prototype后,子类的创建的实例就有会__proto__属性指 ...

  5. 智课雅思词汇---二十四、名词性后缀ary(也是形容词后缀)

    智课雅思词汇---二十四.名词性后缀ary(也是形容词后缀) 一.总结 一句话总结:很多词缀即是名词词缀也是形容词词缀,很多词即是名词也是形容词 1.名词性后缀-tude? 词根词缀:-tude [来 ...

  6. guava API整理

    1,大纲 让我们来熟悉瓜娃,并体验下它的一些API,分成如下几个部分: Introduction Guava Collection API Guava Basic Utilities IO API C ...

  7. OLED取模笔记

  8. Prism5.0新内容 What's New in Prism Library 5.0 for WPF(英汉对照版)

    Prism 5.0 includes guidance in several new areas, resulting in new code in the Prism Library for WPF ...

  9. 【CSAPP】三、程序的机器级表示

    本章基于两种相关的机器语言:Intel IA32和x86-64,前者注重32位,后者注重64位. 本章脉络:c\汇编\机器码之间的关系,数据的表示,控制结构如何实现.运行栈,局部变量的存储,数据结构. ...

  10. Intellij IDEA带参数启动Springboot注意事项

    问题 不同版本的spring-boot-maven-plugin的jvm参数配置有所不同,同时与通过main方法启动springboot程序传递参数也有所不同. 分析 在运行main方法时,可以通过j ...