涉及嵌套使用cursor的问题,保留下以供以后查看。
外层cursor查询的结果作为内层cursor的一个参数,在每次内循环之前生成需要的sql。这里使用了replace将字符替换为外层cursor查询的参数。
统计结果执行 execute immediate 插入表中。
create or replace procedure pday_staticsc(vv_yyyy varchar2,
vv_mm varchar2,
static_intdate int default 0,
static_object varchar2 default NULL) as
-----------------------------------------------------------------
/*--FUNC:通道日统计
入参说明:static_intdate:统计时间,如:19990112,调用者需要对时间进行核对,不输入此参数对昨天统计
static_object: 统计对象,如:'Kas12yWp',不输入此参数对所有对象统计*/
-----------------------------------------------------------------
rel_date smallint;
rel_monstart smallint;
dflag smallint;
static_sname char(24) default NULL;
vv_sql VARCHAR2(8000); --存储sql代码
v_sql VARCHAR2(4000); --存储sql代码
vv_yyyymm varchar2(6);
on_line float; --存储在线时间
out_line float; --存储离线时间
out_times smallint; --存储离线次数
vv_type smallint; --存储在线、离线类型号
vv_time date;
cnt smallint;
vv_type2 smallint;
vv_date date;
type cur is ref cursor;
c1 cur;
--declare
cursor cur_td is
select 代码 as codes from 通道参数表;
begin
--统计在线、离线
if (static_intdate = 0 or static_intdate is null ) then
rel_date := to_char(sysdate - 1, 'yyyyMMdd');
--else
-- rel_date := floor(to_date(static_intdate, 'YYYYMMDD') -
-- to_date('19700101', 'YYYYMMDD'));
end if;
rel_monstart := floor(sysdate- to_date('19700101', 'YYYY-MM-DD hh24:mi:ss'))-1;
--vv_yyyymm := vv_yyyy || vv_mm;
vv_yyyymm:= to_char(sysdate-1,'YYYYMM');
--open cur_td;
for cur_row in cur_td loop
on_line := 0;
out_line :=0;
out_times := 0;
cnt := 1;
vv_type :=0;
vv_time:=to_date('19700101','yyyy-mm-dd hh24:mi:ss');
vv_sql := 'select 当前状态值 type,to_date(substr(年月日*1000000000+时分秒毫秒,1,14),''yyyy-mm-dd hh24:mi:ss'') time
from (select 事件对象名0, 当前状态值,年月日,时分秒毫秒
from (select rownum r_no ,s.事件对象名0,s.当前状态值,s.年月日,s.时分秒毫秒 from 历史事项表 s
where s.事件类型=1004 and s.事件对象名0 in ('':1'') and s.年月日<' ||rel_date || '
order by s.年月日 desc ) row_no where r_no=1
union select s.事件对象名0,s.当前状态值,s.年月日,s.时分秒毫秒
from 历史事项表 s where s.事件类型=1004
and s.年月日='|| rel_date || '
and s.事件对象名0 in ('':1'') ) order by 年月日,时分秒毫秒';
vv_sql := replace(vv_sql,':1',cur_row.codes);
open c1 for vv_sql ;
fetch c1 into vv_type2,vv_date ;
while not c1%NOTFOUND loop
if cnt = 1 then
--判断是否第一条数据
if vv_type2 = 2 then
--第一条数据是上线,取时间:零点
vv_type := 2;
vv_time := to_date(rel_date, 'yyyy-mm-dd hh24:mi:ss');
end if;
else
--不是第一条数据
if vv_type = 2 then
--前一条数据是上线
on_line := on_line + round((vv_date - vv_time) * 24 * 60 * 60); --计算在线时间
vv_type := 0; --计算完之后赋值:0
end if;
if vv_type2 = 2 then
--当前是上线,则赋值
vv_type := 2;
vv_time := vv_date;
else
if vv_type2=3 then
--当前不是上线,则离线次数+1
out_times := out_times + 1;
end if;
end if;
end if;
cnt := cnt + 1;
fetch c1 into vv_type2,vv_date ;
end loop;
close c1;
if vv_type = 2 then
--判断最后一天记录是否是上线
on_line := on_line + round((to_date(rel_date, 'yyyy-mm-dd hh24:mi:ss') -
vv_time + 1) * 24 * 60 * 60 - 1);
else if vv_type = 3 and cnt>2 then
out_times := out_times + 1;
end if;
end if;
on_line := trunc(on_line / 3600, 3);
out_line := 24 - on_line;
--on_line:=24-out_line;
v_sql := 'insert into dayport' || vv_yyyymm ||
' (sname,sdate,time,ontime,offtime,offtimes) values ('''|| cur_row.codes ||''','||rel_monstart||',0,'||on_line||','||out_line||','||out_times||') ';
EXECUTE IMMEDIATE v_sql;
end loop;
--close cur_td;
commit;
end;