PL/SQL 训练07--发现问题
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--发现问题的更多相关文章
- PL/SQL 训练03 --异常
--程序员在开发的时候,经常天真的认为这个世界是完美的,用户如同自己般聪明,总能按照自己设想的方式--操作系统输入数据.但残酷的事实告诉我们,这是不可能的事情,用户总会跟我们相反的方式操作系统--于是 ...
- PL/SQL 训练13--plsql 优化
--数据缓存技术 --PGA和SGA---SGA:系统全局区域--PGA:Process Global Area是为每个连接到Oracle的用户进程保留的内存. ---PLSQL从PGA获取信息的速度 ...
- PL/SQL 训练12--动态sql和绑定变量
--什么是动态SQL?动态PL/SQL--动态SQL是指在运行时刻才构建执行的SQL语句--动态PL/SQL是指整个PL/SQL代码块都是动态构建,然后再编译执行 --动态SQL来可以用来干什么? - ...
- PL/SQL 训练11--包
--所谓包,就是把一组PL/SQL的代码元素组织在一个命名空间下.--一种可以把程序或者其他的PL/SQL元素比如游标.类型.变量的组织结构在一起的结构(包括逻辑结构和物理结构)--包提供了非常重要的 ...
- PL/SQL 训练10--io及文件操作
多数程序只需要通过SQL和底层数据库进行交互--有些情况,不可避免的还是会有一些场景,需要从PL/SQL给外部环境发送信息--或是从一些外部的源读入信息 --这节课介绍下面这些内置包 dbms_out ...
- PL/SQL 训练08--触发器
--什么是触发器呢?--一触即发,某个事件发生时,执行的程序块?--数据库触发器是一个当数据库发生某种事件时作为对这个事件的响应而执行的一个被命名的程序单元 --适合场景--对表的修改做验证--数据库 ...
- PL/SQL 训练05--游标
--隐式游标--通过一个简单的SELECT ...INTO 语句提取一行数据,并放在一个局部变量中,最简单获取数据的途径 --显示游标--可以在声明单元明确的声明一个查询,这样可以在一个或多个程序中打 ...
- PL/SQL 训练04--事务
--pl/sql通过SQL和ORACLE数据库紧密的整合在一起--在pl/sql中可以执行任何操作语句(DML语句),包括INSERT,UPDATE,DELETE,MERGE,也包括查询语句--可否执 ...
- PL/SQL 训练02--集合数组
1. 请列举关联数组.嵌套表.VARRAY三种集合类型的区别区别:1 关联数组只能在plsql中使用,嵌套表,varray可用于sql中,数据库表中的列2 嵌套表,varray必须在使用的时候初始化, ...
- PL/SQL 训练01--基础介绍
--开始介绍变量之前,我们先看下怎么在PLSQL写程序,如下我们写了一个块 declare --声明部分,声明变量 v_name ) :='hello world'; begin --执行区域 dbm ...
随机推荐
- LeetCode第[44]题(Java):Wildcard Matching
题目:通配符匹配 难度:hard 题目内容: Given an input string (s) and a pattern (p), implement wildcard pattern match ...
- 报错org.apache.ibatis.binding.BindingException: Type interface com.atguigu.mybatis.bean.dao.EmployeeMapper is not known to the MapperRegistry.
报错org.apache.ibatis.binding.BindingException: Type interface com.atguigu.mybatis.bean.dao.EmployeeMa ...
- npm install 时总是报phantomjs-prebuilt@2.1.14安装失败
在npm install时总是报如下错误, 尝试单独安装:npm install phantomjs-prebuilt@2.1.14 还是报错 Please report this full log ...
- java reflect反射---Java高级开发必须懂的
理解反射对学习Java框架有很大的帮助,如Spring框架的核心就是使用Java反射实现的,而且对做一些Java底层的操作会很有帮助. 一.Class类的使用 1.万事万物皆对象,( ...
- Netty(RPC高性能之道)原理剖析
1,Netty简述 Netty 是一个基于 JAVA NIO 类库的异步通信框架,用于创建异步非阻塞.基于事件驱动.高性能.高可靠性和高可定制性的网络客户端和服务器端 RPC高性能分析,请参考文章“[ ...
- Java NIO框架 Mina、Netty、Grizzly
Mina Mina(Multipurpose Infrastructure for Network Applications) 是 Apache组织一个较新的项目,它为开发高性能和高可用性的网络应用程 ...
- 7z压缩gopath的src的批处理
7zGoPath.bat @echo off pushd "%~dp0" :config for /f "delims=" %%t in ('powershel ...
- smarty语法
HTML中直接显示数据 <{$data}> foreach循环 <{foreach from=$data item=item key=key}> <li data-ind ...
- 2017.11.15 Add a parameter –serial <serial no> to the Target field.
1 exe创建快捷方式,并且加后缀 program --serial 50114130 这是Win里面的一种调用说明. Please note that the programming logs ...
- 第一次使用stackoverflow的寻求帮助
最近在研究一项资料很少的技术--Drools,遇到一个很棘手的问题,搜遍所有网站,百度.谷歌都找不到解决方案.无奈之下,想起了stackoverflow这个技术问答网站.于是鼓足勇气,用蹩脚的英文在上 ...