我在oracle数据库中编写了数据库调度程序作业,该数据库当前配置为每12小时运行一次。此作业调用存储过程,该存储过程仅在mv刷新完成并且mv上次刷新时间大于清理作业的上次运行时间时执行增量表清理任务。
BEGIN
DBMS_SCHEDULER.create_job (
job_name => 'TABLE_CLEAN_UP_JOB',
job_type => 'STORED_PROCEDURE',
job_action => 'TABLE_CLEAN_UP',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=hourly;interval=12',
enabled => TRUE);
END;
/
以下是存储过程
create or replace procedure TABLE_CLEAN_UP
is
refresh_date timestamp(6);
v_exists NUMBER;
outcome VARCHAR2(100);
cnt NUMBER;
i NUMBER := 0;
begin
SELECT count(1) into cnt FROM all_mviews WHERE owner = 'M_TO' AND mview_name = 'DC_CASHFLOW_VIEW' or mview_name = 'DC_CASHFLOW_VIEW_ZERO' and LAST_REFRESH_TYPE='COMPLETE';
if cnt=2 then
FOR rec IN (SELECT * FROM all_mviews WHERE owner = 'P_SM_TO' AND mview_name = 'DC_CASHFLOW_VIEW' or mview_name = 'DC_CASHFLOW_VIEW_ZERO' and LAST_REFRESH_TYPE='COMPLETE')
LOOP
Select LAST_START_DATE into refresh_date from USER_SCHEDULER_JOBS
where JOB_NAME='TABLE_CLEAN_UP_JOB';
if (CAST(rec.LAST_REFRESH_DATE AS TIMESTAMP) > refresh_date) then
i := i + 1;
end if;
END LOOP;
if i=2 then
delete DC_CASHFLOW_DELTA;
end if;
end if;
end;
/
现在有两个与此相关的问题
首先我没有做过正确的异常处理,所以请指教 如何在上面的存储过程中进行适当的异常处理
还请告知如何将逻辑合并到一个循环中...如果没有发生清理,它应该睡15分钟然后重新尝试。
请告知人们如何进行改进 任何建议将不胜感激
有人可以就此提出建议
答案 0 :(得分:1)
这是一个清理版本(当然未经测试)。我取出了循环,因为它似乎归结为两个计数,我将or
子句中的where
结构更改为in ()
,因为它更简单,你错过了一些括号,所以它会得到错误的结果。
我从不热衷于硬编码模式名称 - 也许它们应该作为参数传递或从配置表中获取?
异常处理看起来很好。 (如果没有no_data_found
,它将失败并显示'TABLE_CLEAN_UP_JOB'
,但我认为它应该在那种情况下失败,因为系统的一部分缺失。也许这个特定情况的异常处理程序可以提供使用raise_application_error
更好的消息,或只记录消息并继续,如果这是您想要它做的事情。这取决于您。)
create or replace procedure table_clean_up
is
v_refresh_date date;
v_table_count_m integer;
v_table_count_p integer;
begin
select count(*) into v_table_count_m
from all_mviews
where owner = 'M_TO'
and mview_name in ('DC_CASHFLOW_VIEW','DC_CASHFLOW_VIEW_ZERO')
and last_refresh_type = 'COMPLETE';
if v_table_count_m = 2 then
select cast(last_start_date as date) into v_refresh_date
from user_scheduler_jobs
where job_name = 'TABLE_CLEAN_UP_JOB';
select count(*) into v_table_count_p
from all_mviews m
where m.owner = 'P_SM_TO'
and m.mview_name in ('DC_CASHFLOW_VIEW', 'DC_CASHFLOW_VIEW_ZERO')
and m.last_refresh_type = 'COMPLETE'
and m.last_refresh_date > v_refresh_date;
if v_table_count_p = 2 then
delete dc_cashflow_delta;
end if;
end if;
end;
我不太了解调度问题。你有一个工作'TABLE_CLEAN_UP_JOB'
每隔12小时调用一次上面的程序,并且在程序内你检查自上次工作运行(12小时前)以来的一些MV刷新,但是如果没有,那么你想要重新安排它在15分钟内重试。我可能错过了一些东西,但为什么不安排它首先每15分钟运行一次?
无论如何,如果你真的想要一个程序调用来重试最多12个小时,你可以尝试以下几点:
create or replace procedure table_clean_up
is
v_refresh_date date;
v_table_count_m integer;
v_table_count_p integer;
v_loopcount integer := 48;
begin
while v_loopcount > 0 loop
select count(*) into v_table_count_m
from all_mviews
where owner = 'M_TO'
and mview_name in ('DC_CASHFLOW_VIEW','DC_CASHFLOW_VIEW_ZERO')
and last_refresh_type = 'COMPLETE';
if v_table_count_m = 2 then
select cast(last_start_date as date) into v_refresh_date
from user_scheduler_jobs
where job_name = 'TABLE_CLEAN_UP_JOB';
select count(*) into v_table_count_p
from all_mviews m
where m.owner = 'P_SM_TO'
and m.mview_name in ('DC_CASHFLOW_VIEW', 'DC_CASHFLOW_VIEW_ZERO')
and m.last_refresh_type = 'COMPLETE'
and m.last_refresh_date > v_refresh_date;
if v_table_count_p = 2 then
delete dc_cashflow_delta;
exit;
end if;
end if;
dbms_lock.sleep(60 * 15);
v_loopcount := v_loopcount -1;
end loop;
end;
(睡眠时间和尝试迭代次数的神奇数字应该作为参数传递或在表格中配置。)