PL/SQL相关知识点

一.输出程序

declare
  --说明部分
begin
  --程序
  dbms_output.put_line('Hello World');
end;

打开输出开关:set serveroutput on

二.pl/sql程序
0.从键盘输入
accept num prompt ‘请输入一个数字’;

1.引用型变量

declare 
   --定义变量保存姓名和薪水
   pname emp.ename%type;
   psal emp.sal%type;
begin
   select ename,sal into pname,psal from emp where empno=7839;
   dbms_output.put_line(pname||'的薪水'||psal);
end;

2.记录型变量

declare 
   emp_rec emp%rowtype;
begin
   select * into emp_rec from emp where emp.empno=7839;
   dbms_output.put_line(emp_rec.ename||'的薪水'||emp_rec.sal);
end;

三.条件语句

declare 
  -- 定义变量保存数字
  pnum number := #
begin
  if pnum = 0 then dbms_output.put_line('您输入的是0');
     elsif pnum = 1 then dbms_output.put_line('您输入的是1');
     elsif pnum = 2 then dbms_output.put_line('您输入的是2');
     else dbms_output.put_line('其他数字');
  end if;
end;

四.循环语句

-- 打印1~10 
declare 
  pnum number := 1;
begin
  loop
       --循环   --退出条件
       exit when pnum > 10;
       dbms_output.put_line(pnum);
       --加一
       pnum := pnum + 1;
  end loop;
end;
declare 
  pnum number :=1;
  begin
    for pnum in 1..9
      loop
        dbms_output.put_line(pnum);
      end loop;  
   end;

五.光标
光标的属性:
%isopen //判断光标是否打开,打开返回true
%rowcount(影响的行数)
%found
%notfound

-- 查询并打印员工的姓名和薪水
declare 
  -- 定义光标
  cursor cemp is select ename,sal from emp;
  pename emp.ename%type;
  psal   emp.sal%type;
begin
  -- 打开光标
  open cemp;

  loop
       --取当前记录
       fetch cemp into pename,psal;
       --exit when 没有取到记录;
       exit when cemp%notfound;

       dbms_output.put_line(pename||'的薪水是'||psal);

  end loop;

  --关闭光标
  close cemp;
end;
-- 查询某个部门的员工姓名
declare 
  cursor cemp(dno number) is select ename from emp where deptno=dno;
  pename emp.ename%type;
begin
  open cemp(20);
  loop
       fetch cemp into pename;
       exit when cemp%notfound;

       dbms_output.put_line(pename);

  end loop;
  close cemp;
end;
-- 涨工资,总裁1000 经理800 其他400
declare 
  -- 定义光标
  cursor cemp is select empno,job from emp;
  pempno emp.empno%type;
  pjob   emp.job%type;
begin
  rollback;  

 --打开光标 
 open cemp;

 loop
      --取一个员工
      fetch cemp into pempno,pjob;
      exit when cemp%notfound;

      --判断职位
      if pjob = 'PRESIDENT' then update emp set sal=sal+1000 where empno=pempno;
         elsif pjob = 'MANAGER' then update emp set sal=sal+800 where empno=pempno;
         else update emp set sal=sal+400 where empno=pempno;
      end if;
 end loop;

 --关闭光标
 close cemp;

 --提交  ---> ACID
 commit;

 dbms_output.put_line('完成');
end;

六.Oracle的异常处理
1.系统定义的例外
not_data_found (没有找到数据)
too_many_rows (select..into语句匹配多个行)
zero_divide(被零除)
value_error(算术或转换错误)
timeout_on_resource(在等待资源时发生超时)

2.用户定义的例外

-- 查询50号部门的员工姓名
declare 
  --定义光标:代表50号部门的员工
  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;

  --pmon进程: process monitor
  close cemp;

exception 
  when no_emp_found then dbms_output.put_line('没有找到员工');  
  when others then dbms_output.put_line('其他例外');  
end;
/

3.进程监视器进程(PMON)
在用户进程失败时(产生异常)执行进程恢复
–清除数据库缓冲区高速缓存
–释放该用户进程使用的资源

七.相关实例
实例一.统计每年入职的员工人数

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

变量:1. 初始值  2.最终得到
count80 number := 0;
count81 number := 0;
count82 number := 0;
count87 number := 0;
*/
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;

实例二.为员工涨工资。从最低工资涨起每人涨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 
*/
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
   fetch cemp into pempno, psal;
   exit when cemp%notfound;

   --涨后的工资总额(使用涨后的工资判断是否大于50000)
   exit when salTotal + psal*0.1 >50000;
   salTotal := salTotal + psal*0.1;
   update emp set sal = sal*1.1 where empno = pempno; 
   countEmp := countEmp + 1;

 end loop;

--关闭光标
  close cemp;  
  commit;
dbms_output.put_line('涨工资的人数为:'||countEmp||',涨后的工资总额为:'||salTotal);

end;

实例三.–用PL/SQL语言编写一程序,实现按部门分段
–(6000以上、6000-3000,3000元以下)统计各个
–工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金)

--创建结果表--存储结果数据
create table msg
(deptno number,
count1 number,
count2 number,
count3 number,
saltotal number);

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 sal;
       end loop;
       close cemp;

       --保存当前部门的结果
       insert into msg values(pdeptno,count1,count2,count3,nvl(saltotal,0));
     end loop;
     --关闭部门的光标
     close cdept;

     --提交
     commit;
     dmbs_output.put_line("统计完成");
   end;

猜你喜欢

转载自blog.csdn.net/lee_charles/article/details/81952230