這段時間開始學習寫存儲過程,主要原因還是因為工作需要吧,本來以為很簡單的,但幾經挫折,豪氣消磨殆盡,但總算搞通了,為了避免后來者少走彎路,特記述與此,同時亦對自己進行鼓勵。
以下是我在開發項目中第一次編寫的存儲,里面用到了嵌套游標和嵌套循環,以及變量的定義方式,第一次不規范的地方還請多多包含,有不明白的地方也可以給我留言,大家互相學習。
--准考證 隨機生成 存儲過程
--生成規則:在用戶選擇考試關聯好考點和考場之后,點擊自動生成准考證,准考證按照 當年考試次數后四位+崗位類型+考點編號+考場編號+座位號 這種規則隨機生成
--備注:一個考場下面只能做三十個人,並且不同崗位類型的考生不能在同一考場,但是同一崗位類型的不同崗位可以在同一個考場
--注意1.變量命名的時候不能和字段名一樣
create or replace procedure card_random_generate(exam_id in number,examNum in varchar,creater in varchar) as
--定義變量
exam_stu_num number;--考試下所有考生的數量
job_name exam_job.jobname%type;--崗位名稱
job_code exam_job.jobcode%type;--崗位編號
job_type exam_job.jobtype%type;--崗位類型
job_stu_num number;--每個崗位下報考的考生數量
point_id exam_point.id%type;--考場對應考點的考點id
point_num exam_point.pointnum%type;--考點編號
point_name exam_point.pointname%type;--考點名稱
room_num exam_point.pointnum%type;--考場編號
room_name exam_point.pointname%type;--考場名稱
room_id ep_exam_point.id%type;--考場在關聯表中對應的id
room_number number;--每個考試下考場的個數
studentid exam_student.id%type;--考生的id
seat_num exam_card.seatnum%type;--座位號
card_num exam_card.cardnum%type;--准考證號
i number;--循環變量
j number;--每個崗位類別需要的考場數
rn number;
--定義查詢崗位游標 規則:1.按照崗位類型分組 2.統計每個類型處於繳費狀態以及審核過的考生的數量 3.崗位狀態是正常狀態
CURSOR student_job IS
select j.jobtype,count( j.jobtype) as job_stu_num from exam_student e inner join exam_job j on e.examid=exam_id
and e.jobid=j.id and e.status='6' and e.ispay='1' and e.state='1' and j.status='1' group by j.jobtype;
--定義 根據考試id查詢關聯的考點 和考場信息(按照考點id升序)
CURSOR exam_point_room IS
select e.id,p.pointname, p.pointnum,p.parent,p.ptype,(select c.pointnum from exam_point c where c.id=p.parent) as point_number,e.isuser from ep_exam_point e
left join exam_point p on e.pointid=p.id or e.centernum=p.id where examid=exam_id and p.ptype='2' and p.state='1' and e.isuser='1' order by p.id;
begin
select count(*) into exam_stu_num from exam_student s where examid=exam_id and s.ispay='1' and s.status='6' and s.state='1';--所有已審核,已繳費成功,未生成准考證的考生數量
dbms_output.put_line('該考試下所有的考生數量是:'||exam_stu_num);
--一級循環標准 按崗位類型
for c in student_job loop
begin
job_type:=c.jobtype;--崗位類型
job_stu_num:=c.job_stu_num;--每個崗位類型下的考生數量
if(mod(job_stu_num,30)=0) then
j:=job_stu_num/30;
else
j:=floor(job_stu_num/30)+1;
end if;
dbms_output.put_line('崗位類型是:'||job_type||',報考崗位的考生數量是:'||job_stu_num||',崗位需要的考場數量是:'||j);
--二級循環 按照每個崗位下考生的數量
while job_stu_num>0
loop
begin
--三級循環標准 按照考場
for d in exam_point_room loop
-- if(d.isuser=2)then
-- exit;
-- end if;
begin
if(d.ptype=2) then
point_num:=d.point_number;
-- select id into point_id from exam_point where id=d.parent;--查詢考場的父節點考點的考點id
point_id:=d.parent;--考場的父節點考點的考點id
room_num:=d.pointnum;
room_name:=d.pointname;
room_id:=d.id;
dbms_output.put_line('考點編號是:'|| point_num||',考場編號是:'||room_num);
i:=1;
while i<=30 --每個考場座位號都是從01-30
loop
begin --這里是取滿足狀態的學生 隨機取一個把生成的准考證與學生id一一對應,在此之前一直非常無奈的是在oracle中要想查詢排過序的特定行結果一般都要用到子查詢,而在存儲過程中
--給變量賦值時候在子查詢里面賦值一直不能編譯成功,幾經嘗試后來放在外面把子查詢作為一個整體在外面實現了賦值功能,好坑啊,不過最終還是實現了,呵呵
select b.id into studentid from (select s.* ,rownum as rn from exam_student s inner join exam_job j on s.jobid=j.id and s.examid=j.examid
and s.status='6' and s.state='1' and s.ispay='1' where s.examid=exam_id and j.jobtype=job_type) b where rn=job_stu_num ;
dbms_output.put_line('考生id是:'||studentid);
if(i<10) then
dbms_output.put_line('准考證號是:'|| examNum||job_type||point_num||room_num||'0'||i||',考場名稱是:'||room_name);
card_num:=examNum||job_type||point_num||room_num||'0'||i;--拼接准考證號
seat_num:='0'||i;
insert into exam_card values(seq_exam_card_id.nextval,exam_id,studentid,point_id,room_num,seat_num,card_num,creater,sysdate);
commit;
else
dbms_output.put_line('准考證號是:'|| examNum||job_type||point_num||room_num||i||',考場名稱是:'||room_name);
card_num:=examNum||job_type||point_num||room_num||i;--拼接准考證號
seat_num:=i;
insert into exam_card values(seq_exam_card_id.nextval,exam_id,studentid,point_id,room_num,seat_num,card_num,creater,sysdate);
commit;
end if;
update exam_student set status='7' where id=studentid;--改變學生的狀態為7 生成准考證狀態
commit;
i:=i+1;
job_stu_num:=job_stu_num-1;
end;
if(job_stu_num<=0) then
update ep_exam_point set isuser='2' where id=room_id;
commit;
exit;--退出循環
end if;
end loop;
end if;
end;
if(job_stu_num=0)then
exit;--退出循環
end if;
if(job_stu_num>0) then
update ep_exam_point set isuser='2' where id=room_id;
commit;
exit;--退出循環(此時一個考場排滿了,退出循環進入下一個考場繼續排)
end if;
end loop;
end;
end loop;
end;
end loop;
end card_random_generate;