好长时间没写过存储过程了,这几天项目中刚好要用到存储过程,没想到一点都记不起来了,又翻了翻以前记录的资料,才算完成。
--创建一个存储过程 传入两个参数, in 表示传入的参数,返回的参数用out表示
create or replace procedure count1(starttime in varchar2,endtime in varchar2 ) as
-- 用游标接收数据
cursor mycu is select t1.* ,b1.name
from (
select p.duty ,sum(p.invest) as num_ztz ,sum(b.accumulatinvest) as num_ljwc,sum(b.planinvest) as num_dnjh ,sum(b.completedinvest) as num_dnwc ,
sum(b.monthinvest) as num_dywc , count(p.id) as lj_xm,
count(case when (s2.name='已投产' or s2.name='已开工' or s2.name='已竣工' or s2.name='试生产') then p.id end ) as lj_kg ,
count(case when s.name='新建' then p.id end ) as xj_xm ,
count(case when s.name='新建' and (s2.name='已投产' or s2.name='已开工' or s2.name='已竣工' or s2.name='试生产') then p.id end ) as xj_kg,
count(case when s.name='续建' then p.id end ) as xjs_xm,
count(case when s.name='续建' and (s2.name='已投产' or s2.name='已开工' or s2.name='已竣工' or s2.name='试生产') then p.id end ) as xjs_kg
from pro_project p left join pro_build b on b.proid=p.id left join pro_basevalue s on (s.id=p.protype ) left join pro_basevalue s2 on s2.id=p.prostatus left join pro_basevalue s3 on s3.id=p.duty
where delstate is null and s.name!='在谈' and s.name!='后续' and to_char(p.dynamictime,'yyyy-MM')>=starttime and to_char(p.dynamictime,'yyyy-MM')<=endtime
group by p.duty,s3.priority order by s3.priority
) t1 left join pro_basevalue b1 on b1.id=t1.duty ;
per_ndwc_ number(16,4):=0;
per_wcztz_ number(16,4):=0;
lj_kgl_ number(16,4):=0;
xj_kgl_ number(16,4):=0;
xjs_kgl_ number(16,4):=0;
begin
for cu in mycu -- 开始循环 还有其它的循环方式,个人觉得这种比较方便
loop
if cu.num_dnjh!=0 then
per_ndwc_:=cu.num_dnwc/cu.num_dnjh;
end if;
if cu.num_ztz!=0 then
per_wcztz_:=cu.num_ljwc/cu.num_ztz;
end if;
if cu.lj_xm!=0 then
lj_kgl_:=cu.lj_kg/cu.lj_xm;
end if;
if cu.xj_xm!=0 then
xj_kgl_:=cu.xj_kg/cu.xj_xm;
end if;
if cu.xjs_xm!=0 then
xjs_kgl_:=cu.xjs_kg/cu.xjs_xm;
end if;
insert into pro_statement(id,num_ztz,num_ljwc,num_dnjh,num_dnwc,num_dywc,per_ndwc,per_wcztz,
lj_xm,lj_kg,lj_kgl,xj_xm,xj_kg,xj_kgl,xjs_xm,xjs_kg,xjs_kgl,create_time,data_type,tname)
values(seq_pro_statement.nextval,cu.num_ztz,cu.num_ljwc,cu.num_dnjh,cu.num_dnwc,cu.num_dywc,per_ndwc_,per_wcztz_,
cu.lj_xm,cu.lj_kg,lj_kgl_,cu.xj_xm,cu.xj_kg,xj_kgl_,cu.xjs_xm,cu.xjs_kg,xjs_kgl_,sysdate,'1',cu.name);
end loop;
end;
-- 同样也是一个存储过程,返回两个参数,一个是游标类型,一个数据列数(因为列数是动态的,在resultset中取值时无法确定有几列)
create or replace procedure execByJb_type(synch_cursor out synch.synch_cursor,column_count out number) as
cursor mycu is select jb_type from rep_synch group by jb_type ;
jb_type_ varchar2(50):='';
sql_ varchar2(2000):=' select to_char(to_date(sj_time,''yyyy-mm-dd hh24:mi:ss''),''mm'') 月份 ';
begin
for cu in mycu
loop
jb_type_:=cu.jb_type ;
column_count:=mycu%rowcount;
sql_:=sql_||', count(case when jb_type='''||jb_type_||''' then id end) '||jb_type_;
end loop;
sql_:=sql_||',count(id) 总计 from rep_synch group by to_char(to_date(sj_time,''yyyy-mm-dd hh24:mi:ss''),''mm'') order by to_char(to_date(sj_time,''yyyy-mm-dd hh24:mi:ss''),''mm'') ';
open synch_cursor for sql_;
end;
//java代码中调用存储过程
CallableStatement cs=null;
try {
String sql="{ call pro(?,?) }";
cs=conn.prepareCall(sql);
//调用存储过程,一共有两个返回值,第一个返回游标,第二个返回 列数
cs.registerOutParameter(1,oracle.jdbc.OracleTypes.CURSOR);
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.NUMBER);
result=cs.execute();
int count=cs.getBigDecimal(2).intValue();
rs=(ResultSet) cs.getObject(1);
ResultSetMetaData metaData=rs.getMetaData();
while (rs!=null&&rs.next()) {
Map<String,Object> map=new HashMap<String, Object>();
for (int i = 1; i <=count+2; i++) {
map.put(metaData.getColumnName(i), rs.getObject(i)); //以当前列名为key,当前值为value保存当前行
columns.add(metaData.getColumnName(i)); //获取当前列的列名
}
list.add(map);//将一整行完整数据放入list中
}
}
//最终将列名与数据集都返回,在前台只需要循环就好了
--------------------------以下部分转自 http://www.cnblogs.com/mingforyou/archive/2012/06/06/2538063.html 写的很详细
declare
jobno number;
begin dbms_job.submit(
jobno,--定时器ID,系统自动获得
'PRC_INSERT;', --what执行的过程名
sysdate,--next_date,定时器开始执行的时间,这样写表示立即执行
'sysdate + 15/1440'--interval,设置定时器执行的频率,这样写每隔15分钟执行一次
);
commit;
end;
这里第一个参数是任务编号,系统自动赋值。也可以采用isubmit来手动指定
第二个参数是需要执行的任务过程,代码长的话,可以将它写到一个存储过程里,再放到里面调用,比如'pro_test;' (pro_test假定为一个存储过程名)
第三个参数是,自动任务第一次执行的时间,如果需要它立即执行,则使用sysdate
最后一个参数,系统根据该参数的值指定下一次的执行时间。
declare
jobno
number;
begin
dbms_job.remove(45);
commit;
end;
exec dbms_job.remove(83);--删除一个定时器
exec dbms_job.run(84);--运行一个定时器
exec DBMS_JOB.BROKEN(83,SYS.DIUTIL.INT_TO_BOOL(1));--停止一个定时器
exec DBMS_JOB.INTERVAL(84, 'sysdate + 60/1440');--改变一个定时器的执行频率成每隔一小时执行一次
select * from user_jobs;——查看调度任务
select * from dba_jobs_running;——查看正在执行的调度任务
select * from dba_jobs;——查看执行完的调度任务
定时器的参数说明:
myjob参数是由Submit()过程返回的binary_ineger。这个值用来唯一标识一个工作;
what参数是将被执行的PL/SQL代码块,这里指的是一个存储过程,注意名字后面的分号;
next_date参数指识何时将运行这个工作。写Job的时候可以不指定该值;
interval参数何时这个工作将被重执行。
关于interval的设置,参考以下几个例子:
1、 每分钟执行
Interval => TRUNC(sysdate,’mi’) + 1 / (24*60)
2、 每天定时执行
例如:每天的凌晨2点执行
Interval => TRUNC(sysdate) + 1 +2 / (24)
3、 每周定时执行
例如:每周一凌晨2点执行
Interval => TRUNC(next_day(sysdate,2))+2/24 --星期一,一周的第二天
4、 每月定时执行
例如:每月1日凌晨2点执行
Interval =>TRUNC(LAST_DAY(SYSDATE))+1+2/24
5、 每季度定时执行
例如每季度的第一天凌晨2点执行
Interval => TRUNC(ADD_MONTHS(SYSDATE,3),'Q') + 2/24
6、 每半年定时执行
例如:每年7月1日和1月1日凌晨2点
Interval => ADD_MONTHS(trunc(sysdate,'yyyy'),6)+2/24
7、 每年定时执行
例如:每年1月1日凌晨2点执行
Interval =>ADD_MONTHS(trunc(sysdate,'yyyy'),12)+2/24