zoukankan      html  css  js  c++  java
  • 慕课网笔记之oracle开发利器-PL/SQL基础

    实例1--if语句

    /* 慕课网Oracle数据库开发必备之PL/SQL_2-3
    
    判断用户从键盘输入的数字
    
    1.如何使用if语句
    
    2.接收一个键盘的输入(字符串) */
    
    set serveroutput on;
    
    --接收一个键盘输入
    
    --num:地址值,含义是:在该地址上保存了输入的值
    
    accept num prompt '请输入一个数字';
    
    declare --定义变量保存键盘输入的数字
    
    pnum number := #
    
    begin --执行if语句进行条件判断
    
    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;
    
    /

    实例2--while语句

    /*
    慕课网Oracle数据库开发必备之PL/SQL_2-4 
    while循环语句打印数字1-10
    */
    set serveroutput on
    declare
    pnum number := 1;
    begin
    while pnum<=10  loop
    dbms_output.put_line (pnum);
    pnum := pnum +1;
    end loop;
    end;
    /


    实例3--loop语句

    /* 慕课网Oracle数据库开发必备之PL/SQL_2-4 
    
    loop循环语句打印数字1-10 */ 
    
    set serveroutput on 
    
    declare pnum number := 1;
    
    begin loop exit when pnum>10; 
    
    dbms_output.put_line (pnum); 
    
    pnum := pnum +1; 
    
    end loop; 
    
    end; 
    
    /

    实例3--for语句

    /* 慕课网Oracle数据库开发必备之PL/SQL_2-4 
    
    for循环语句打印数字1-10 
    
    for循环的格式: 
    
    for i in 1..9 loop
    
     
    
    end loop; */ 
    
    set serveroutput on 
    
    declare pnum number := 1 ; 
    
    begin for pnum in 1..10 loop 
    
    dbms_output.put_line (pnum); 
    
    end loop; 
    
    end; 
    /

    慕课网建表sql:

    select * from dept
    DROP TABLE DEPT;
    CREATE TABLE DEPT
           (DEPTNO NUMBER(2) CONSTRAINT PK_DEPT PRIMARY KEY,
      DNAME VARCHAR2(14) ,
      LOC VARCHAR2(13) ) ;
    DROP TABLE EMP;
    CREATE TABLE EMP
           (EMPNO NUMBER(4) CONSTRAINT PK_EMP PRIMARY KEY,
      ENAME VARCHAR2(10),
      JOB VARCHAR2(9),
      MGR NUMBER(4),
      HIREDATE DATE,
      SAL NUMBER(7,2),
      COMM NUMBER(7,2),
      DEPTNO NUMBER(2) CONSTRAINT FK_DEPTNO REFERENCES DEPT);
    INSERT INTO DEPT VALUES
      (10,'ACCOUNTING','NEW YORK');
    INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
    INSERT INTO DEPT VALUES
      (30,'SALES','CHICAGO');
    INSERT INTO DEPT VALUES
      (40,'OPERATIONS','BOSTON');
    INSERT INTO EMP VALUES
    (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
    INSERT INTO EMP VALUES
    (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
    INSERT INTO EMP VALUES
    (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
    INSERT INTO EMP VALUES
    (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
    INSERT INTO EMP VALUES
    (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
    INSERT INTO EMP VALUES
    (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
    INSERT INTO EMP VALUES
    (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
    INSERT INTO EMP VALUES
    (7788,'SCOTT','ANALYST',7566,to_date('13-JUL-87')-85,3000,NULL,20);
    INSERT INTO EMP VALUES
    (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
    INSERT INTO EMP VALUES
    (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
    INSERT INTO EMP VALUES
    (7876,'ADAMS','CLERK',7788,to_date('13-JUL-87')-51,1100,NULL,20);
    INSERT INTO EMP VALUES
    (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
    INSERT INTO EMP VALUES
    (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
    INSERT INTO EMP VALUES
    (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
    DROP TABLE BONUS;
    CREATE TABLE BONUS
      (
      ENAME VARCHAR2(10)  ,
      JOB VARCHAR2(9)  ,
      SAL NUMBER,
      COMM NUMBER
      ) ;
    DROP TABLE SALGRADE;
    CREATE TABLE SALGRADE
          ( GRADE NUMBER,
      LOSAL NUMBER,
      HISAL NUMBER );
    INSERT INTO SALGRADE VALUES (1,700,1200);
    INSERT INTO SALGRADE VALUES (2,1201,1400);
    INSERT INTO SALGRADE VALUES (3,1401,2000);
    INSERT INTO SALGRADE VALUES (4,2001,3000);
    INSERT INTO SALGRADE VALUES (5,3001,9999);
    COMMIT;

    游标语法及第一个实例:

    --查询并打印员工的薪水(游标的使用)
    set serveroutput on;
    declare
    cursor cemp is select empno,ename,sal from emp;
    pempno emp.empno%type;
    pename emp.ename%type;
    psal emp.sal%type;
    begin
    open cemp;
    loop
    fetch cemp into pempno,pename,psal;
    --dbms不能放于此
    
    exit when cemp%notfound;
    dbms_output.put_line('编号:'||pempno||',姓名:'||pename||',工资:'||psal);
    end loop;
    close cemp;
    end;
    /

     3-3给员工涨工资(游标的使用)

    --给员工涨工资,总裁1000,经理800,其他400(游标的使用)
    set serveroutput on;
    declare
    --定义光标代表哪些员工涨工资
    cursor cemp is select empno,job from emp;
    pempno emp.empno%type;
    pjob emp.job%type;
    begin
    --打开光标
    open cemp;
    loop
    --取出一个员工
    fetch cemp into pempno,pjob;
    exit when cemp%notfound;
    --判断员工的职位
    if 'PRESIDENT'=pjob then update emp set sal= sal+1000 where empno= pempno;
    elsif 'MANAGER'=pjob 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;
    /

     3-4 光标的属性和光标数的限制

    3-4-1

    /*
    1.光标的四个属性:
    %found;%notfound;%isopen 光标是否打开;    %rowcount光标影响的行数
    2.光标数的限制
    */
    set serveroutput on;
    declare
    cursor cemp is select empno,job from emp;
    pempno emp.empno%type;
    pjob emp.job%type;
    begin
    open cemp;
    if cemp%isopen then dbms_output.put_line('光标是打开的');
    else dbms_output.put_line('光标是关闭的');
    end if;
    close cemp;
    end;
    /

    run:

    匿名块已完成
    光标是打开的

    3-4-2

    /*
    1.光标的四个属性:
    %found;%notfound;%isopen 光标是否打开;    %rowcount光标影响的行数(可以理解为光标已经取出的数总和)
    2.光标数的限制
    SQL> conn sys/password@host:1521/XE as sysdba;
    SQL> show parameters cursor
      NAME                TYPE        VALUE
      open_cursors        integer     300
    修改光标数的限制
    alter system set open_cursors=400 scope=both;
    scope的取值:both,memory,spfile(数据库需要重启)
    */
    set serveroutput on;
    declare
    cursor cemp is select empno,job from emp;
    pempno emp.empno%type;
    pjob emp.job%type;
    begin
    open cemp;
    loop
    fetch cemp into pempno,pjob;
    exit when cemp%notfound;
    dbms_output.put_line('光标属性rowcount:'||cemp%rowcount);
    end loop;
    close cemp;
    end;
    /

    run:

    匿名块已完成
    光标属性rowcount:1
    光标属性rowcount:2
    光标属性rowcount:3
    光标属性rowcount:4
    光标属性rowcount:5
    光标属性rowcount:6
    光标属性rowcount:7
    光标属性rowcount:8
    光标属性rowcount:9
    光标属性rowcount:10
    光标属性rowcount:11
    光标属性rowcount:12
    光标属性rowcount:13
    光标属性rowcount:14 

    3-5 带参数的光标

    --查询某个部门中员工的姓名(得定义一个带参的光标
    set serveroutput on;
    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;
    /

    run:
    匿名块已完成
    部门的员工姓名 :SMITH
    部门的员工姓名 :JONES
    部门的员工姓名 :SCOTT
    部门的员工姓名 :ADAMS
    部门的员工姓名 :FORD

    【光标】的总结

    光标就是一个结果集(result set)

    打开光标:open c1(cursor)

    取一行光标的值:fetch c1 into pename;(去一行到变量中)

    关闭光标:close c1;

     5-2案例:统计每年入职的员工人数

    /*
    统计每年入职的员工人数
    select to_char(hiredate,'yyyy') from emp;
    步骤:1.游标代表查出的结果
    2.变量来接受遍历游标的每列值
    3.定义变量来存储统计结果
    4.if判断语句每年的人数
    5.打印结果
    6.结束,关闭游标等
    */
    set serveroutput on
    declare
    cursor ctemp is select to_char(hiredate,'yyyy') from emp;
    phiredate varchar2(10);
    count80 number :=0;
    count81 number :=0;
    count82 number :=0;
    count87 number :=0;
    begin
    open ctemp;
    loop
    fetch ctemp into phiredate;
    exit when ctemp%notfound;
    if '1980'=phiredate then count80 := count80+1;
    elsif '1981'=phiredate then count81 := count81+1;
    elsif '1982'=phiredate then count82 := count82+1;
    else count87 := count87+1;
    end if;
    end loop;
    close ctemp;
    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;
    /

    run as:
    匿名块已完成
    1980入职员工人数:1
    1981入职员工人数:10
    1982入职员工人数:1
    1987入职员工人数:2

     5-3 案例2- 员工涨工资问题

    /*
    为员工涨工资。从最低工资员工涨起每人涨现有工资的10%,但所有员工的工资总额不能超过5万元。请计算涨工资
    的人数和涨工资后的工资总额,并输出涨工资人数及涨后工资总额。
    分析:1.定义游标select empno,sal from emp order by sal;是一个集合,所以需要定义游标
    2.定义变量来接收游标的列值
    3.定义变量-工资总额=涨前总额+sal*0.1,
    4.定义变量-涨工资人数
    */
    set serveroutput on;
    declare
    cursor ctemp is select empno,sal from emp order by sal;
    pempno emp.empno%type;
    psal1 emp.sal%type;--涨前
    psal2 emp.sal%type;--涨后
    sumsal number(7,2);
    sumemp number := 0;
    begin
    open ctemp;
    select sum(sal) into sumsal from emp;
    loop
    exit when sumsal >50000;
    fetch ctemp into pempno,psal1;
    exit when ctemp%notfound;
    psal2 := psal1+ psal1*0.1;
    exit when (sumsal+psal1*0.1) > 50000;--在涨之前先判断涨后是否会大于50000
    update emp set sal= psal2 where empno= pempno;
    sumsal := sumsal + psal1*0.1;
    sumemp := sumemp+1;
    end loop;
    close ctemp;
    dbms_output.put_line('涨后工资总额:'||sumsal);
    dbms_output.put_line('涨工资人数'||sumemp);
    commit;
    end;
    /

     run as:

    匿名块已完成 涨后工资总额:40067.5 涨工资人数14

    匿名块已完成 涨后工资总额:44074.25 涨工资人数14

    匿名块已完成 涨后工资总额:48481.68 涨工资人数14

    匿名块已完成 涨后工资总额:49939.14 涨工资人数7

    匿名块已完成 涨后工资总额:49939.14 涨工资人数0

    匿名块已完成 涨后工资总额:49939.14 涨工资人数0

     5-4-1 自己的理解成一张表了。涉及两张表的员工涨工资问题

    /*
    用pl/sql语言编写一段程序,实现按部门分段(6000以上,(6000,3000),3000元以下)统计各工资段的职工人数、
    以及各部门的工资总额(工资总额中不包括奖金).
    分析:1.定义3个游标,有参游标:select empno,sal from emp where deptno=?;
        无参游标:select distinct(deptno) ddeptno from emp order by ddeptno;
                 select distinct(deptno)  from emp;
        2.定义变量来接收游标的列值。
        3.定义变量存储 三个阶段的 职工人数,
        4.定义变量各部门的工资总额;
        5.对列值,判断是否在三个阶段的哪个阶段,然后相应的职工人数+1
    */
    set serveroutput on;
    declare
    cursor c1 is select distinct(deptno)  from emp ;
    cursor c2(dno number) is select sal from emp where deptno= dno;
    pdeptno emp.deptno%type;
    psal emp.sal%type;
    sumemp10_6000 number := 0;
    sumemp10_6000_3000 number := 0;
    sumemp10_3000 number := 0;
    sumemp20_6000 number := 0;
    sumemp20_6000_3000 number := 0;
    sumemp20_3000 number := 0;
    sumemp30_6000 number := 0;
    sumemp30_6000_3000 number := 0;
    sumemp30_3000 number := 0;
    sumsal10 number(7,2);
    sumsal20 number(7,2);
    sumsal30 number(7,2);
    begin
    open c1;
    loop
    fetch c1 into pdeptno;
    exit when c1%notfound;
    open c2(pdeptno);
    loop 
    fetch c2 into psal;
    exit when c2%notfound;
    if 10 = pdeptno 
    then 
    if psal>6000 then sumemp10_6000 := sumemp10_6000+1 ;
    elsif psal<3000 then sumemp10_3000 := sumemp10_3000+1;
    else sumemp10_6000_3000 := sumemp10_6000_3000+1;
    end if;
    elsif 20 = pdeptno
    then
    if psal>6000 then sumemp20_6000 := sumemp20_6000+1 ;
    elsif psal<3000 then sumemp20_3000 := sumemp20_3000+1;
    else sumemp20_6000_3000 := sumemp20_6000_3000+1;
    end if;
    else
    if psal>6000 then sumemp30_6000 := sumemp30_6000+1;
    elsif psal<3000 then sumemp30_3000 := sumemp30_3000+1;
    else sumemp30_6000_3000 := sumemp30_6000_3000+1;
    end if;
    end if;
    end loop;
    close c2;
    if 10 = pdeptno then select sum(sal) into sumsal10 from emp where deptno=pdeptno;
    elsif 20 = pdeptno then select sum(sal) into sumsal20 from emp where deptno=pdeptno;
    else select sum(sal) into sumsal30 from emp where deptno=pdeptno;
    end if;
    end loop;
    close c1;
    dbms_output.put_line('部门10,6000以上的人数:'||sumemp10_6000);
    dbms_output.put_line('部门10,6000-3000的人数:'||sumemp10_6000_3000);
    dbms_output.put_line('部门10,3000以下的人数:'||sumemp10_3000);
    dbms_output.put_line('部门20,6000以上的人数:'||sumemp20_6000);
    dbms_output.put_line('部门20,6000-3000的人数:'||sumemp20_6000_3000);
    dbms_output.put_line('部门20,3000以下的人数:'||sumemp20_3000);
    dbms_output.put_line('部门30,6000以上的人数:'||sumemp30_6000);
    dbms_output.put_line('部门30,6000-3000的人数:'||sumemp30_6000_3000);
    dbms_output.put_line('部门30,3000以下的人数:'||sumemp30_3000);
    dbms_output.put_line('部门10,总工资:'||sumsal10);
    dbms_output.put_line('部门20,总工资:'||sumsal20);
    dbms_output.put_line('部门30,总工资:'||sumsal30);
    end;
    /

    run as:
    匿名块已完成
    部门10,6000以上的人数:0
    部门10,6000-3000的人数:2
    部门10,3000以下的人数:1
    部门20,6000以上的人数:0
    部门20,6000-3000的人数:3
    部门20,3000以下的人数:2
    部门30,6000以上的人数:0
    部门30,6000-3000的人数:1
    部门30,3000以下的人数:5
    部门10,总工资:10950
    部门20,总工资:13275
    部门30,总工资:12200

     5-4-2 正常做法 将查询结果放入一个表格msg_muke中

    /*
    用pl/sql语言编写一段程序,实现按部门分段(6000以上,(6000,3000),3000元以下)统计各工资段的职工人数、
    以及各部门的工资总额(工资总额中不包括奖金).
    */
    /*
    分析:
    1.有哪些部门:select deptno from dept;->光标->循环->退出条件:notfound
    2.部门中员工的薪水:select sal from emp where deptno=?;带参数的光标->循环->退出条件:notfound
    3.变量:1.初始值2.如何得到
    每个段的员工人数;
    count1 number,count2 nunber,count3 number
    每个部门的员工工资总额
    saltotal number;
    select sum(sal) from emp where deptno=?
    */
    set serveroutput on;
    declare
    cursor c1 is select deptno from dept;
    cursor c2(dno number) is select sal from emp where deptno=dno;
    pdeptno dept.deptno%type;
    psal emp.sal%type;
    count1 number;
    count2 number;
    count3 number;
    saltotal number;
    begin
    
    open c1;
    loop
    count1 := 0;--<3000
    count2 := 0;-->=3000 and <6000
    count3 := 0;-->=6000
    fetch c1 into pdeptno;
    exit when c1%notfound;
    
    open c2(pdeptno);
    loop
    fetch c2 into psal;
    exit when c2%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 c2;
    select sum(sal) into saltotal from emp where deptno=pdeptno;
    insert into msg_muke values(pdeptno,count1,count2,count3,nvl(saltotal,0));
    end loop;
    close c1;
    commit;
    dbms_output.put_line('任务执行完成');
    end;
    /

    run as:

    匿名块已完成
    任务执行完成
    插入的表格:

    5-6 多表的游标

    /*
    
    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=??);
    */
    set serveroutput on;
    declare
    --系的光标
    cursor cdept is select dno,dname from dep;
    pdno dep.dno%type;
    pdname dep.dname%type;
    --学生成绩光标
    cursor cgrade(tcname varchar2,tdno number) is select grade from sc where cno=(select cno from course where cname=tcname )
    and sno in(select sno from student where dno=tdno);
    pgrade sc.grade%type;
    pavggrade number;
    count1 number;count2 number;count3 number;
    pcname varchar2 := '大学物理';
    begin
    open cdept;
    loop
    fetch cdept into pdno,pdname;
    exit when cdept%notfounmd;
    select avg(grade) into pavggrade from sc where cno=(select cno from course where cname=pcname )
    and dno= pdno;
    count1 := 0;
    count2 := 0;
    count3 := 0;
    
    open cgrade(pcname,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 (pcname,pdname,count1,count2,count3,pavggrade);
    
    end loop;
    close cdept;
    commit;
    dbms_output.put_line('执行完成');
    end;
    /

    run as:

    小结:

    pl/sql:procedure language /sql;

    pl/sql 是oracle对sql语言过程化的扩展;

  • 相关阅读:
    pycurl之公共方法--请求/上传/下载,解析json
    BAT启动关闭VMWARE的虚拟机
    LINUX免密登录SSH下的操作之自动COPY部署到其他机器
    python 可迭代对象
    python itertools 迭代器增加元素
    python django
    《Linux下mysql安装》
    linux下安装mysql
    hive基本语法
    linux连接工具MobaXterm下载及使用
  • 原文地址:https://www.cnblogs.com/westward/p/5215565.html
Copyright © 2011-2022 走看看