[*用Oracle来创建学生信息管理系统(续2)*]
2016-12-02 09:49
381 查看
–应用报表
–1、输入班级号,打印输出当前班级信息及当前班级中的学生信息–创建报表打印的PL/SQL块如下:
–分析:
–一、根据要求,需要动态输入班级号,可使用带参数的游标;
–二、班级号是主键,可以用select into 语句直接获取班级信息;
–三、学生有多个,需要单独处理每个学生,可用游标;
–四、会存在班号输入错误,引入异常处理
–Oracle数据库中,所有的查询语句select的使用,
–系统都会产生相应的游标
–所有的游标分两类:隐式游标,显式游标需要通过游标类型变量的定义
declare /*声明带参数的游标*/ cursor student_cursor(p_clno class.clno%type) is select * from student where clno=p_clno; /*学生记录类型*/ student_record student%rowtype; /*班级记录类型*/ class_record class%rowtype; /*班级编号*/ v_clno class.clno%type; /*班级人数*/ v_count number(2); v_sex varchar2(2); --报表块主体部分 begin v_clno:=upper('&p_clno'); /*取得班级信息*/ select * into class_record from class where clno=v_clno; /*取得班级人数*/ select count(*) into v_count from student where clno=v_clno group by clno; dbms_output.put_line (class_record.dept||'系'||class_record.grade||class_record.branch ||'总共有:'||v_count||'人'); dbms_output.put_line('_____________________________'); /*取得当前班级的学生信息*/ open student_cursor(v_clno); loop fetch student_cursor into student_record; exit when student_cursor%notfound; if student_record.sex='1'then v_sex:='男'; else v_sex:='女'; end if; dbms_output.put_line('学号:'||student_record.sno||',姓名:' ||student_record.name||',年龄:'||student_record.age||',性别:' ||v_sex||',入学日期:' ||to_char(student_record.entrance,'yyyy-mm-dd')); end loop; close student_cursor; exception when no_data_found then dbms_output.put_line('指定的班级号不存在!'); end;
2、根据业务要求,需定义一个报表打印,要求输出所有课程的信息
(课程编号,课程名称,课程学分);
并打印输出针对当前课程按照授课教师分组,所教学生的人数
以及学生的平均得分;
(教师号,教师姓名,学生人数,学生平均得分)
分析:
需要输出所有课程的信息,涉及多条数据处理,需要引入游标
再按照课程分组,输出每个教师所教学生的人数及平均得分时,
需首先确定课程,分析一、中的数据**
创建视图:教师号,教师姓名,学生人数,学生平均得分
解决方案:
1、创建视图,按课程和教师分组,统计每个教师所教学生人数、
其所负责课程名称及所教学生在此课程所得成绩的平均值。
create or replace view vw_course_teacher as select c.cno,t.tno,t.name tname, count(*) stu_count,trunc(avg(st.grade),2) score_avg from teacher t join st st on t.tno=st.tno join course c on t.cno=c.cno group by(c.cno,t.tno,t.name);
2、创建报表打印的PL/SQL如下:
declare /*课程游标*/ cursor course_cursor is select cno,name,score from course; /*基于vw_course_teacher声明带参数的游标*/ cursor vw_c_t_cursor(p_cno course.cno%type) is select * from vw_course_teacher where cno=p_cno; /*课程记录类型*/ course_record course%rowtype; /*vw_course_teacher记录类型*/ vw_c_t_record vw_course_teacher%rowtype; /*统计选择当前课程的人数*/ v_stu_count int; /*统计选择当前课程的学生的平均分*/ v_score_avg number(4,2); begin open course_cursor; loop /*取得课程记录*/ fetch course_cursor into course_record; exit when course_cursor%notfound; /*打印课程信息*/ dbms_output.put_line('课程号:'||course_record.cno); dbms_output.put_line('课程名:'||course_record.name); dbms_output.put_line('总学分:'||course_record.score); dbms_output.put_line(''); /*根据当前课程编号,打开基于vw_course_teacher的游标*/ open vw_c_t_cursor(p_cno=>course_record.cno); v_stu_count:=0; v_score_avg:=0; /*打印报表表头*/ dbms_output.put_line(LPAD('教师号',10,' ') ||LPAD('教师姓名',12,' ') ||LPAD('学生人数',12,' ')||LPAD('平均分',10,' ')); loop fetch vw_c_t_cursor into vw_c_t_record; exit when vw_c_t_cursor%notfound; v_stu_count:=v_stu_count+vw_c_t_record.stu_count; v_score_avg:=v_score_avg+ vw_c_t_record.score_avg*vw_c_t_record.stu_count; dbms_output.put_line(LPAD(vw_c_t_record.tno,10,' ') ||LPAD(vw_c_t_record.tname,12,' ') ||LPAD(vw_c_t_record.stu_count,12,' ') ||LPAD(vw_c_t_record.score_avg,10,' ')); end loop; dbms_output.put_line(LPAD(RPAD(' ',22,'-'),44,' ')); dbms_output.put_line('总计'||LPAD(v_stu_count,30,' ') ||LPAD(v_score_avg/v_stu_count,10,' ')); close vw_c_t_cursor; dbms_output.put_line(''); dbms_output.put_line(LPAD('- ',44,'- ')); end loop; close course_cursor; end;
异常处理
1、异常简介:在编写PL/SQL块时,应该捕捉并处理各种可能出现的异常。
如果不捕捉和处理异常,Oracle会将错误传递到调用环境,
整个程序运行自动终止,并不提示任何错误信息;
如果捕捉并处理异常,那么Oracle会在PL/SQL块内解决运行错误。
在PL/SQL,一般将异常处理部分放在PL/SQL程序体的后半部,其语法结构为:
exception when exception1 then <对于exception1的处理语句> when exception2 then <对于exception2的处理语句> when others then <对于其他异常的处理语句> end;
Others不是必需的,但Others必须放在最后。
对两数相除可能出现的错误进行处理
declare v_n1 int:=&n1; v_n2 int:=&n2; v_div int; begin v_div:=v_n1/v_n2; dbms_output.put_line(v_n1||'/'||v_n2||'='||v_div); exception when zero_divide then dbms_output.put_line('除数不能为零!'); when others then dbms_output.put_line('出现未知错误!'); end;
2、异常处理
Oracle中的异常包括预定义异常、非预定义异常和自定义异常三种类型
预定义异常
declare emp_record emp%rowtype; begin select * into emp_record from emp where sal=&p_sal; dbms_output.put_line('雇员姓名:'||emp_record.ename||',工资:'||emp_record.sal); exception when no_data_found then dbms_output.put_line('不存在该工资的雇员!'); when too_many_rows then dbms_output.put_line('该工资的雇员有多个!'); end;
由于经常对学生信息表进行操作,为方便管理和提高代码执行速度,
需要将学生信息表的增、删、改、查封装到包内使用子过程实现,
以方便应用程序JAVA调用。
分析
使用包可以使程序设计模块化,而且可以提高程序的执行效率。
对于学生信息增加操作,可使用记录类型作为输入参数的过程实现。
对于查询操作,需要根据学生号查询学生信息,并能返回所有学生信息
对于修改操作,需要能够根据指定的条件,动态构造修改语句,在Oracle中
可以使用EXECUTE IMMEDIATE过程动态地执行本地SQL。
参考的解决方案
1、定义包规范如下:
create or replace package student_pack is /*统计学生人数*/ v_count int; /*增加学生信息*/ procedure add_student(student_record student%rowtype); /*根据指定条件修改学生信息*/ procedure update_student(p_modifiers varchar2,p_condition varchar2); /*根据学生号删除学生信息*/ procedure del_student(p_sno student.sno%type); /*根据学生号查询学生信息*/ function get_student(p_sno student.sno%type) return student%rowtype; /*定义基于记录类型的嵌套表*/ type student_table_type is table of student%rowtype; /*获得所有学生的信息*/ function get_student return student_table_type; end student_pack;
2、对于student_pack包的包体代码如下:
create or replace package body student_pack is /*check_student是包体的私有子程序*/ function check_student(p_sno student.sno%type) return boolean is v_count int; begin select count(*) into v_count from student where sno=p_sno; if v_count>0 then return true; else return false; end if; end check_student; /*实现add_student过程*/ procedure add_student(student_record student%rowtype) is begin if check_student(student_record.sno)=false then insert into student values(student_record.sno,student_record.name, student_record.age,student_record.sex, student_record.entrance,student_record.address, student_record.clno,student_record.family); dbms_output.put_line('添加成功!'); else dbms_output.put_line('添加失败:学生编号冲突!'); end if; exception when others then dbms_output.put_line('添加错误:'||SQLCODE||'----'||SQLERRM); end add_student; /*实现update_student过程*/ procedure update_student(p_modifiers varchar2,p_condition varchar2) is begin execute immediate 'update student'||'set' ||p_modifiers||'where'||p_condition; exception when others then dbms_output.put_line('修改出错:'||SQLCODE||'----'||SQLERRM); end; /*实现del_student过程*/ procedure del_student(p_sno student.sno%type) is begin if check_student(p_sno)=true then delete from student where sno=p_sno; dbms_output.put_line('删除成功!'); else dbms_output.put_line('删除失败:指定的学生不存在!'); end if; exception when others then dbms_output.put_line('删除出错:'||SQLCODE||'----'||SQLERRM); end del_student; /*实现get_student函数*/ function get_student(p_sno student.sno%type) return student%rowtype is student_record student%rowtype; no_result exception; begin if check_student(p_sno)=true then select * into student_record from student where sno=p_sno; return student_record; else raise no_result; end if; exception when no_result then raise_application_error(-20099,'查询的学生不存在'); when others then /*输出错误编码和消息*/ --dbms_output.put_line(SQLCODE||'----'||SQLERRM); raise_application_error(-20100,'查询出错'); end get_student; /*实现get_student函数*/ function get_student return student_table_type is student_table student_table_type; begin select * bulk collect into student_table from student; return student_table; end get_student; /*获取学生总人数*/ begin select count(*) into v_count from student; end student_pack; --用于测试student_pack功能的PL/SQL语句如下: /*添加过程测试*/ declare student_record student%rowtype; begin student_record.sno:=&add_sno; student_record.name:=&add_name; student_record.age:=&add_age; student_record.sex:=&add_sex; student_record.entrance:=&add_entr; student_record.address:=&add_addr; student_record.clno:=&add_clno; student_record.family:=&add_fami; student_pack.add_student(student_record); end; /*删除过程测试*/ declare student_record student%rowtype; begin student_record.sno:=&del_sno; student_pack.del_student(student_record.sno); end;
–包的调用
call student_pack.get_student('1462105');
–过程调用
call zxx_package2.sal_pro1('CLERK',0.01);
–函数的调用
var vsal number; call zxx_package2.avg_sal(10) into:vsal select zxx_package2.avg_sal(10) from dual;
call student_pack.check_student('1462119'); declare begin student_pack.get_student('1462119'); end;
var v_ck boolean; call student_pack.check_student('1462140819') into:v_ck; select student_pack.check_student('1462140819') from dual;
相关文章推荐
- [*用Oracle来创建学生信息管理系统(续1)*]
- [*用Oracle来创建学生信息管理系统*]
- 学生信息管理系统(wampserver+php+oracle+前端_环境搭建)
- 用于参考的学生信息管理系统(数据库简单 可自己参考创建)
- 学生信息管理系统
- 【原创视频教程】学生信息管理系统1--登陆
- Oracle & JSP 开发的小型信息管理系统 (一) 说明文档
- Oracle & JSP 开发的小型信息管理系统 (六) 运行截图
- Oracle & JSP 开发的小型信息管理系统 (五) 源代码4
- 学生信息管理系统简单模拟(C语言实现)
- 【原创视频教程】学生信息管理系统3--学员添加
- 【原创视频教程】学生信息管理系统5--学员成绩管理
- 【原创视频教程】学生信息管理系统4--成绩添加
- 【原创视频教程】学生信息管理系统1--登陆
- 【原创视频教程】学生信息管理系统5--学员成绩管理
- 学生学籍信息管理系统
- 学生信息管理系统
- 【原创视频教程】学生信息管理系统2--主窗体
- 【原创视频教程】学生信息管理系统2--主窗体
- Oracle & JSP 开发的小型信息管理系统 (三) 源代码2