zoukankan      html  css  js  c++  java
  • Oracle学习笔记(十一)

    例外:
    例外是程序设计语言提供的一种功能,用来增强程序的健壮性和容错性.


    例外分为:
    系统例外
    自定义例外

    系统例外分为:
    No_data_found(没有找到数据)、
    Too_many_rows(select ... into 语句匹配多个行)、
    Zero_Divide(被零除)、
    Value_error(算数或转换错误,负数不能在实数范围开平方,abc不能转换成123)、
    Timeout_on_resource(在等待资源时发生超时(分布式数据库))


    No_data_found
    组函数使用这个Exception无效,默认组函数在没有记录时会有默认的返回值 如count会返回0,max、min、avg等会返回空,这样的话是不会触发异常的

    事例一:
    --没有找到数据
    set serveroutput on
    declare
    pename emp.ename%type;

    begin
    --查询员工号是1234的员工姓名
    select ename into pename from emp where empno=1234;
    exception
    when no_data_found then
    DBMS_OUTPUT.PUT_LINE('没有找到该员工');
    when others then
    DBMS_OUTPUT.PUT_LINE('其他例外');
    end;
    /

    事例二:
    --匹配多个行
    set serveroutput on
    declare
    pename emp.ename%type;

    begin
    --查询所有10号部门的员工姓名
    select ename into pename from emp where deptno=10;
    exception
    when too_many_rows then
    DBMS_OUTPUT.PUT_LINE('select...into匹配了多个行');
    when others then
    DBMS_OUTPUT.PUT_LINE('其他例外');
    end;
    /
    事例三:
    --被零除
    set serveroutput on
    declare
    --定义一个基本变量
    pnum number;

    begin
    pnum :=1/0;
    exception
    when zero_divide then
    DBMS_OUTPUT.PUT_LINE('1:0不能做除数');
    DBMS_OUTPUT.PUT_LINE('2:0不能做除数');
    when others then
    DBMS_OUTPUT.PUT_LINE('其他例外');
    end;
    /
    例外四:
    -----value_error算数或转换错误
    set serveroutput on
    declare
    --定义一个基本变量
    pnum number;

    begin
    pnum :='abc';
    exception
    when value_error then
    DBMS_OUTPUT.PUT_LINE('算数或者转换错误');
    when others then
    DBMS_OUTPUT.PUT_LINE('其他例外');
    end;
    /

    自定义例外
    (1)定义变量,类型是Exception
    (2)使用raise抛出自定义例外

    事例:
    set serveroutput on
    declare

    cursor cemp is select ename from emp where deptno=50;
    --定义一个基本变量
    pename emp.ename%type;

    --自定义例外
    no_emp_found exception;

    begin
    open cemp;
    --取出一条记录
    fetch cemp into pename;
    if cemp%notfound then
    --抛出例外
    raise no_emp_found;
    end if;

    --关闭游标
    --oralce自动启动进程监视器pmon(process monition)
    close cemp;
    exception
    when no_emp_found then
    DBMS_OUTPUT.PUT_LINE('没有找到员工');
    when others then
    DBMS_OUTPUT.PUT_LINE('其他例外');
    end;
    /

    PL/SQL程序设计综合案例
    程序设计方法
    瀑布模型
    需求分析
    设计
    概要设计
    详细设计
    编码
    测试
    部署
    运营

    思考:所需要的SQl语句和变量
    变量:1、初始值是多少
    2、最终值如何得到

    综合案例1
    统计每年入职的员工人数
    Total 1980 1981 1982 1987
    ======== ======= ========== ======== =========
    14 1 10 1 2

    注意:员工的入职年份已知

    方法一(函数方式):
    select count(*) Total,
    sum(decode(to_char(hiredate,'YYYY'),'1980',1,0)) "1980",
    sum(decode(to_char(hiredate,'YYYY'),'1981',1,0)) "1981",
    sum(decode(to_char(hiredate,'YYYY'),'1982',1,0)) "1982",
    sum(decode(to_char(hiredate,'YYYY'),'1987',1,0)) "1987"
    from emp;


    /*
    SQL语句
    select to_char(hiredate,'yyyy') from emp;
    --->光标--->循环--->退出条件:notfound

    变量:1.初始值2.如何得到
    每年入职的员工人数:
    count80 number:=0;
    count81 number:=0;
    count82 number:=0;
    count87 number:=0;
    */

    PL/SQL开发:

    set serveroutput on
    declare
    --定义光标
    cursor cemp is select to_char(hiredate,'yyyy') from emp;
    phiredate varchar2(4);
    --每年入职的员工人数

    count80 number:=0;
    count81 number:=0;
    count82 number:=0;
    count87 number:=0;

    begin
    --打开光标
    open cemp;
    loop
    --取出一个员工的入职年份
    fetch cemp into phiredate;
    exit when cemp%notfound;
    --判断入职年份
    if phiredate= '1980' then count80:=count80+1;
    elsif phiredate='1981' then count81:=count81+1;
    elsif phiredate='1982' then count82:=count82+1;
    else count87:=count87+1;
    end if;


    end loop;
    --关闭光标
    close cemp;
    --输出结果
    dbms_output.put_line('Total:'||' '||(count80+count81+count82+count87));
    dbms_output.put_line('1980:'||' '||count80);
    dbms_output.put_line('1981:'||' '||count81);
    dbms_output.put_line('1982:'||' '||count82);
    dbms_output.put_line('1987:'||' '||count87);
    end;
    /

    综合案例2
    为员工涨工资.从最低工资涨起没人涨10%,但工资总额不能超过5万元,请计算涨工资的人数和涨工资后的工资总额,并输出涨工资人数及工资总额
    SQl语句
    select empno,sal from emp order by sal;
    -->光标-->循环-->退出条件:1、工资总额>5W 2、%notfound

    变量:1、初始值 2、如何得到
    涨工资的人数:
    countEmp number := 0;
    涨工资后的工资总额:
    salTotal number;
    1、select sum(sal) into salTotal from emp;
    2、涨后的工资总额=涨前的工资总额 + sal *0.1

    PL/SQL开发:
    set serveroutput on
    declare
    --定义光标
    cursor cemp is select empno,sal from emp order by sal;
    pempno emp.empno%type;
    psal emp.sal%type;
    --涨工资的人数
    countEmp number:=0;

    --涨后的工资总额
    salTotal number;

    begin
    --得到工资总额的初始值
    select sum(sal) into salTotal from emp;

    --打开光标
    open cemp;

    loop
    --1、工资总额>5W
    exit when salTotal > 50000;
    --取一个员工涨工资
    fetch cemp into pempno,psal;
    --2、%notfound
    exit when cemp%notfound;
    if (salTotal + psal*0.1) > 50000
    then dbms_output.put_line('超额不能涨工资了');

    --涨工资
    else update emp set sal=sal*1.1 where empno=pempno;
    --人数+1
    countEmp:=countEmp+1;

    --2、涨后的工资总额=涨前的工资总额+sal*0.1
    salTotal:=salTotal+psal*0.1;
    end if;
    end loop;

    --关闭光标
    close cemp;
    commit;
    --打印结果
    dbms_output.put_line('涨薪水人数:'||' '||countEmp);
    dbms_output.put_line('涨后的工资总额:'||' '||salTotal);
    end;
    /

    综合案例3
    用PL/SQL语言编写一程序,实现按部门分段(6000以上、(6000,3000)、3000元以下)统计各工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金)
    建立一张表
    create table msg(
    deptno number,
    count1 number,
    count2 number,
    count3 number,
    saltotal number
    );


    分析:
    SQl语句
    1、有哪些部门
    select deptno from dept;
    -->光标-->循环-->退出条件:1、工资总额>5W 2、%notfound
    2、部门中员工的薪水
    select sal from emp where deptno=? -->带一个参数的光标-->循环-->退出条件:notfound(=true)

    变量:1、初始值 2、如何得到
    每个段的员工人数:
    count1 number := 0;
    count2 number := 0;
    count3 number := 0;

    每个部门的工资总额:
    salTotal number;
    1、select sum(sal) into salTotal from emp where deptno=???;
    2、累加(优越)

    PL/SQL开发:
    set serveroutput on
    declare
    --部门的光标
    cursor cdept is select deptno from dept;
    pdeptno dept.deptno%type;

    --部门中员工的光标
    cursor cemp(dno number) is select sal from emp where deptno=dno;
    psal emp.sal%type;

    --每个段的员工人数:
    count1 number;
    count2 number;
    count3 number;

    --每个部门的工资总额:
    salTotal number;

    begin
    --打开部门的光标
    open cdept;

    loop
    --取一个员工涨工资
    fetch cdept into pdeptno;
    exit when cdept%notfound;

    --初始化的工作
    count1:=0;
    count2:=0;
    count3:=0;

    --得到部门的工资总额
    --1、select sum(sal) into salTotal from emp where deptno=???
    select sum(sal) into salTotal from emp where deptno=pdeptno;

    --取部门中员工的薪水
    open cemp(pdeptno);
    loop
    --取一个员工的薪水
    fetch cemp into psal;
    exit when cemp%notfound;

    --判断薪水的范围
    if psal<3000 then
    count1:=count1+1;
    elsif psal>=3000 and psal<6000 then
    count2:=count2+1;
    else
    count3:=count3+1;
    end if;
    end loop;
    --关闭部门光标
    close cemp;

    --保存当前部门的结果
    insert into msg values(pdeptno,count1,count2,count3,nvl(salTotal,0));
    end loop;
    commit;
    dbms_output.put_line('统计完成!!');
    end;
    /

    查看结果:
    select * from msg;

    综合案例4
    用PL/SQL语言编写一个程序.按系(系名)分段统计(成绩小于60分,60-85分,85分以上)"大学物理"课程各分数段的学生人数,及各系学生的平均成绩.
    (多表查询和子查询)

    脚本student.sql
    drop table sc;
    drop table course;
    drop table student;
    drop table teacher;
    drop table dep;

    create table dep(
    dno number(2),
    dname varchar2(30),
    director number(4),
    tel varchar(8)
    );

    create table teacher(
    tno number(4),
    tname varchar2(10),
    title varchar2(20),
    hiredate date,
    sal number(7,2),
    bonus number(7,2),
    mgr number(4),
    deptno number(2)
    );

    create table student(
    sno number(6),
    sname varchar2(8),
    sex varchar2(2),
    birth date,
    passwd varchar2(8),
    dno number(2)
    );

    create table course(
    cno varchar2(8),
    cname varchar2(20),
    credit number(1),
    ctime number(2),
    quota number(3)
    );

    create table sc(
    sno number(6),
    cno varchar2(8),
    grade number(3)
    );

    alter table dep add(constraint pk_deptno primary key(dno));
    alter table dep add(constraint dno_number_check check(dno>=10 and dno<=50));
    alter table dep modify(tel default 62795032);
    alter table student add(constraint pk_sno primary key(sno));
    alter table student add(constraint sex_check check(sex='男' or sex='女'));
    alter table student modify(birth default sysdate);
    alter table course add(constraint pk_cno primary key(cno));
    alter table sc add(constraint pk_key primary key(cno,sno));
    alter table teacher add(constraint pk_tno primary key(tno));
    alter table sc add(foreign key(cno) references course(cno));
    alter table sc add(foreign key(sno) references student(sno));
    alter table student add(foreign key(dno) references dep(dno));
    alter table teacher add(foreign key(deptno) references dep(dno));

    insert into dep values(10,'计算机学院',9469,'62785234');
    insert into dep values(20,'自动化学院',9581,'62775234');
    insert into dep values(30,'无线电学院',9791,'62778932');
    insert into dep values(40,'信息管理学院',9611,'62785520');
    insert into dep values(50,'微纳电子学院',2031,'62797686');

    insert into teacher values(9468,'CHARLES','PROFESSOR','17-Dec-17',8000,1000,null,10);
    insert into teacher values(9469,'SMITH','PROFESSOR','17-Dec-17',5000,1000,9468,10);
    insert into teacher values(9470,'ALLEN','ASSOCIATE PROFESSOR','20-Feb-16',4200,500,9469,10);
    insert into teacher values(9471,'WARD','LECTURER','22-Feb-17',3000,300,9469,10);
    insert into teacher values(9581,'JONES','PROFESSOR','2-Apr-2016',6500,1000,9468,20);
    insert into teacher values(9582,'MARTIN','ASSOCIATE PROFESSOR','28-Sep-2018',4000,800,9581,20);
    insert into teacher values(9583,'BLAKE','LECTURER','1-May -2019',3000,300,9581,20);
    insert into teacher values(9791,'CLAKE','PROFESSOR','9-Jun-2016',5500,null,9468,30);
    insert into teacher values(9792,'SCOTT','ASSOCIATE PROFESSOR','09-Dec-17',4500,null,9791,30);
    insert into teacher values(9793,'BAGGY','LECTURER','17-Nov-2017',3000,null,9791,30);
    insert into teacher values(9611,'TURNER','PROFESSOR','8-Sep-2018',6000,1000,9468,40);
    insert into teacher values(9612,'ADAMS','ASSOCIATE PROFESSOR','12-Jan-17',4800,800,9611,40);
    insert into teacher values(9613,'JAMES','LECTURER','3-Dec-19',2800,200,9611,40);
    insert into teacher values(2031,'FORD','PROFESSOR','3-Dec-18',5500,null,9468,50);
    insert into teacher values(2032,'MILLER','ASSOCIATE PROFESSOR','23-Jan-2018',4300,null,2031,50);
    insert into teacher values(2033,'MIGEAL','LECTURER','23-Jan-2019',2900,null,2031,50);
    insert into teacher values(2034,'PEGGY','LECTURER','23-Jan-2020',2800,null,2031,50);

    更改格式
    alter session set nls_date_language='AMERICAN';
    19-JUN-01


    保存数据的表格
    create table msg1(
    coursename varchar2(20),
    dname varchar2(20),
    count1 number,
    count2 number,
    count3 number,
    avggrade number
    );

    SQL语句
    1、得到有哪些系
    select dno,dname from dep;
    -->光标-->循环-->退出条件:notfound

    2、得到系中,选修了"大学物理" 课程学生的成绩
    select grade from sc where cno=(select cno from course where cname='大学物理') and sno in (select sno from student where dno=??);
    -->带参数的光标-->循环-->退出条件:notfound

    变量:1、初始值 2、如何得到
    每个分数段的人数
    count1 number;
    count2 number;
    count3 number;

    每个系选修了"大学物理"学生的平均成绩
    avggrade number;
    1、算数运算
    2、select avg(grade) into avggrade from sc where cno=(select cno from course where cname='大学物理') and sno in (select sno from student where dno=??);


    PL/SQL开发:
    set serveroutput on
    declare
    --系的光标
    cursor cdept is select dno,dname from dep;
    pdno dep.dno%type;
    pdname dep.dname%type;

    --成绩光标
    cursor cgrade(coursename varchar2,depno number) is select grade from sc where
    cno=(select cno from course where cname=coursename) and sno in (select sno from student where dno=depno);
    pgrade sc.grade%type;

    --每个分数段的人数:
    count1 number;count2 number;count3 number;

    --每个系选修了"大学物理"学生的平均成绩:
    avggrade number;

    --课程名称
    pcourseName varchar2(20):='大学物理';

    begin
    --打开部门的光标
    open cdept;
    loop
    --取一个系的信息
    fetch cdept into pdno,pdname;
    exit when cdept%notfound;

    --初始化的工作
    count1:=0;count2:=0;count3:=0;

    --系的平均成绩
    select avg(grade) into avggrade from sc
    where cno=(select cno from course where cname=pcourseName)
    and sno in (select sno from student where dno=pdno);

    --取系中,选修了大学物理的学生成绩
    open cgrade(pcourseName,pdno);
    loop
    --取一个学生的成绩
    fetch cgrade into pgrade;
    exit when cgrade%notfound;

    --判断成绩的范围
    if pgrade<60 then
    count1:=count1+1;
    elsif pgrade>=60 and pgrade<85 then
    count2:=count2+1;
    else
    count3:=count3+1;
    end if ;

    end loop;
    close cgrade;
    --保存当前部门的结果
    insert into msg1 values(pcourseName,pdname,count1,count2,count3,avggrade);
    end loop;
    close cdept;

    commit;
    dbms_output.put_line('统计完成!!');
    end;
    /

    select * from msg1;

  • 相关阅读:
    ★《唐琅探案》后记【2】
    ★《唐琅探案》后记【2】
    《OD学hadoop》第一周0625 LINUX作业一:Linux系统基本命令(一)
    《OD学hadoop》第一周0626
    《OD学hadoop》mac下使用VMware Fusion安装centos
    《OD学hadoop》第一周0625
    《OD学hadoop》第二阶段Java编程基础
    《OD学hadoop》Linux基础
    《OD学hadoop》Hadoop前置
    《OD学算法》常用算法集合
  • 原文地址:https://www.cnblogs.com/liuyangfirst/p/6418580.html
Copyright © 2011-2022 走看看