1. 程式人生 > >Oracle 遊標實現學生學號自動生成

Oracle 遊標實現學生學號自動生成

每個學生都有唯一專屬的學號,現有學號格式為ABCDEFGHIJ共10位數字,其中AB表示學院編號;CD表示專業編號;EF表示年級;GH表示班級編號;IJ表示學生序號。

已知:2018年開學之際,已知每個專業的總人數和需要分配的班級數,請為每位同學分配唯一的學號。

要求:每個專業的班級序號是連續的,班內學生學號是連續。

學院編號 專業編號 班級總數 專業人數
02 03 6 187
02 03 2 71
07 08 21 632

 

最後生成的學號如:

0203180101

0203180102

 ~  ~  ~

0708180101

0708180102

 ~  ~  ~

drop table temp;
create table temp(
    academy_id varchar2(4) not null,
    major_id varchar2(4) not null,
    class_allnum number not null,
    student_allnum number(4) not null);

insert into temp values('02','03',6,187);
insert into temp values('02','03',2,71);
insert into temp values('07','08',21,632);
select * from temp;


--說明文件:
--1.預先建立一張原始資料表,確定每個學院的每個專業一共有多人,且要分幾個班級
--2.建立帶引數的過程,傳入年級(如:18級,傳入字元:18)
--3.引數說明:
--	cursor temp_num is select * from temp  初始化表temp的遊標
--	curTemp 遊標物件
--	student_num 每個班級的人數(整數),如:187人分個6班,每班31人
--	student_tempnum 每個班級的人數(小數),如:187人分個6班,每班31.16人
--		  由於oracle在數值型別轉時(從小數到整數),會進行四捨五入運算,而不是取整運算,所以通過比較以上兩者的數值,來判斷每個班級應分配多少人
--		  如:某專業623人打算分21個班級(623/21=29.66),則初打算每班分配29,而不是30人
--	student_otherNum 多出來的學生,如:187人分個6班,多出1人
--	stud_i 迴圈變數:學生編號
--	class_i 迴圈變數:班級編號

create or replace procedure prodStudNum(year_id char)
as
cursor temp_num is select * from temp;
curTemp temp%rowtype;
student_num int;
student_tempnum number;
student_otherNum int;
stud_i int;
class_i int;
begin
delete from stud;
for curTemp in temp_num loop
	student_num:=curTemp.student_allnum/curTemp.class_allnum;
	student_tempnum:=curTemp.student_allnum/curTemp.class_allnum;
	if student_num>student_tempnum then 
		student_num:=student_num-1;
	end if;
	student_otherNum:=curTemp.student_allnum-student_num*curTemp.class_allnum;
    	for class_i in 1..curTemp.class_allnum loop
        	for stud_i in 1..Student_num loop
			if class_i<10 then 
				if stud_i<10 then
					insert into stud(sno) values(year_id||curTemp.academy_id||curTemp.major_id||'0'||class_i||'0'||stud_i);
				else
					insert into stud(sno) values(year_id||curTemp.academy_id||curTemp.major_id||'0'||class_i||stud_i);
				end if;
			else
				if stud_i<10 then
					insert into stud(sno) values(year_id||curTemp.academy_id||curTemp.major_id||class_i||'0'||stud_i);
				else
					insert into stud(sno) values(year_id||curTemp.academy_id||curTemp.major_id||class_i||stud_i);
				end if;
			end if;
        	end loop;
    	end loop;
	student_num:=student_num+1;
	for class_i in 1..curTemp.class_allnum loop
		exit when student_otherNum=0;
		if class_i<10 then 
			if student_num<10 then
				insert into stud(sno) values(year_id||curTemp.academy_id||curTemp.major_id||'0'||class_i||'0'||student_num);
			else
				insert into stud(sno) values(year_id||curTemp.academy_id||curTemp.major_id||'0'||class_i||student_num);
			end if;
		else
			if student_num<10 then
				insert into stud(sno) values(year_id||curTemp.academy_id||curTemp.major_id||class_i||'0'||student_num);
			else
				insert into stud(sno) values(year_id||curTemp.academy_id||curTemp.major_id||class_i||student_num);
			end if;
		end if;
		student_otherNum:=student_otherNum-1;
    	end loop;
end loop;
end;
/
show error
exec prodStudNum('18')
select * from stud order by sno;