zoukankan      html  css  js  c++  java
  • Oracle--存储过程(重要)

    存储过程

    之前的PL/SQL块, 匿名的PL/SQL 没有名字, 数据库不会存储, 每一次执行: 都要经过编译-运行
    存储过程: 都是命名的PL/SQL, 存储在数据库中,作为数据库的一个对象,类似表, 只需要第一次把这个存储过程
    编译(把这个存储过程保存到数据库), 后面调用存储过程, 不需要进行再编译, 直接运行
    -- 关键字: Procedure

    语法:

    create [or replace] procedure 存储过程名
            [(参数1 model 类型1,参数2  model 类型2,.....)]
       is/as
            [变量。游标声明]
       begin  --相当于java中的{
              --执行语句
       [exception
            --异常处理
       ]
       end; 

    注意: 存储过程: 变量的声明, 游标声明,...  写在is/as 之后, 没有declare

    参数列表:  参数名   model(IN: 输入参数, out:输出参数, inout: 输入输出参数, 数据的转换)    数据类型

    无参的存储过程:例:

    --编写一个无参的存储过程,  查询7788员工姓名,薪水
    --选中这个存储过程, 点执行,  编译存储过程, 并且把存储过程保存到数据库
    -- 我们还需要查看这个存储过程是否有错误, 有错误,一定需要修改, 修改之后一定在一次编译
    create or replace procedure  proc_findNameAndSal 
    is
      --定义变量
      v_ename emp.ename%type;
      v_sal emp.sal%type;
    begin
      select ename , sal into v_ename,v_sal from emp where empno = 7788;
      
      dbms_output.put_line(v_ename||v_sal);
    end;

    运行存储过程:

     --第一种调用方式,通过pl/sql运行
    begin
      proc_findNameAndSal;
    end;
    --第二种方式: 在小黑屏,dos命令窗口:
    dbms_output.put_line() 默认不显示, 打开显示
    set serverout on;
    exec 存储过程名;

    有参的存储过程:例:

      存储过程的参数 model
      in 输入参数: 这个参数只能由调用者传递过程, 这个参数不能再存储过程内部修改 ,默认model 就是in

    --查询指定员工编号的姓名薪水
    create or replace procedure  proc_findNameAndSal2(eno in number) 
    is
      --定义变量
      v_ename emp.ename%type;
      v_sal emp.sal%type;
    begin
      --eno := 7788;  --错误的
      select ename , sal into v_ename,v_sal from emp where empno = eno;
      
      dbms_output.put_line(v_ename||v_sal);
    end;

    调用:

    begin
      proc_findNameAndSal2(7902);
    end;

    存储过程授权

    --授予存储过程的执行权限 给其他用户
    -- 做实验, 一定把用户先断开,再连接
    -- grant  execute on 存储过程名  to 用户名;
    grant  execute on proc_findNameAndSal to zhangsan;
    --撤销权限 
    revoke execute on proc_findNameAndSal from zhangsan;

    删除存储过程

    --语法: drop  procedure  存储过程名;
    drop procedure proc_findNameAndSal;

    传值方式:

    --给某个部门加薪,最多一次加薪不能超出1000
    --  部门参数,  加薪:钱也是参数  in
    create or replace procedure  proc_addSal(dno emp_back3.deptno%type, sal1 emp_back3.sal%type) 
    is
    begin
       if  sal1 > 1000 then
         dbms_output.put_line('加薪超过标准,不能加薪');
       else
          update emp_back3 set sal = sal + sal1  where deptno =  dno;
          commit;
       end if;
    end;
    -- 执行
    begin
      --传递参数: 第一种方式: 按位置传参
      --proc_addSal(10,501);
      
      --第二种方式: 按参数名 
      --语法: 参数名 => 值
       --proc_addSal(dno => 10,sal1 => 501);
       proc_addSal( sal1 => 501, dno => 20);
    end;

    out 参数

    输出参数, 返回给调用者, 这个参数必须要在存储过程内部赋值

    --编写一个存储过程, 根据用户编号,查询员工的姓名, 薪水(返回给调用)
    create or replace procedure proc_findNameAndSal2( eno emp.empno%type,
      p_ename out emp.ename%type, p_sal out emp.sal%type
    )
    as
      --定义变量
    begin
       select ename , sal into p_ename , P_sal from emp where empno = eno;
    end;
    
    --带输出参数的存储过程的调用, 必须定义变量来接收
    declare
       --接收输出参数的变量
       ename emp.ename%type;
       sal emp.sal%type;
    begin
       --把输出参数的结果赋值给变量
       proc_findNameAndSal2(7566,ename,sal);
       dbms_output.put_line(ename||', '||sal);
    end;

    使用游标

    -- 查询指定部门的员工信息,
    -- 部门编号:输入参数   员工信息(多行数据), 使用游标  输出参数,  动态游标(SYS_REFCURSOR)
    -- 返回游标给调用者,一定不能再存储过程中关闭游标, 关闭游标, 相当于 清空数据
    create  or  replace  procedure  proc_findEmpsByDno(
       dno emp.deptno%type, emps out sys_refcursor
    )
    is
    begin
       --打开游标,绑定sql语句
       if emps%isopen then
          null;
        else 
           open emps for select * from emp where deptno = dno;
        end if;
    end;
    --调用 返回游标的存储过程
    declare
      --定义一个系统动态游标,接收
      c_empsCursor  sys_refcursor;
      v_emp emp%rowtype;
    begin
      proc_findEmpsByDno(20,c_empsCursor);
      --提取数据:  不要在打开游标, 应该在存储过程中,已经打开游标
      --直接提取数据
      loop
        fetch c_empsCursor into v_emp;
        exit when c_empsCursor%notfound;
        dbms_output.put_line(v_emp.ename||', '||v_emp.job||', '||v_emp.sal);
      end loop;
      --关闭游标
      close c_empsCursor;
    end;

    例题:.查找scott用户的emp表中的所有数据,如果job为MANAGER
    工资大于2500,则下调百分之10;如果小于2500 则增加百分之10,
    如果job为SALESMAN 工资小于1500 则上调百分之10;
    最后符合条件的人.插入到test表中.并且打印符合条件的人数的个数.
    Test表结构如下:
      Ename varchar2
      Sal1 number --原来的工资
      Sal2 number --修改之后的工资

    create or replace procedure  proc_findJobsalCreatetable(c_emp out sys_refcursor)
    is
    begin
      --打开游标,绑定sql语句
       if c_emp%isopen then
          null;
        else 
           open c_emp for  select * from emp;
        end if;
    end;
    -- 运行
    declare 
     --定义一个系统动态游标,接收
      v_emp sys_refcursor;
      myemp emp%rowtype;
      v_sal emp.sal%type;
      -- 统计符合条件的个数
      num1 number := 0; -- MANAGER
      num2 number := 0;
    begin
      proc_findJobsalCreatetable(v_emp);
      loop 
         fetch v_emp into myemp;
         exit when v_emp%notfound;
         if myemp.job = 'MANAGER' then
            if myemp.sal >= 2500 then
              v_sal := myemp.sal*0.9;
            elsif myemp.sal < 2500 then
              v_sal := myemp.sal*1.1;
            end if;
             dbms_output.put_line(myemp.ename||' ,'||myemp.job||' ,'||v_sal);
             -- 将数据插入到test表中
             insert into test values(myemp.ename,myemp.sal,v_sal);
             num1 := num1+1;
     
         elsif myemp.job = 'SALESMAN' then
            if myemp.sal < 1500 then
              v_sal := myemp.sal*1.1;
            else
               v_sal := myemp.sal;
            end if;
             dbms_output.put_line(myemp.ename||' ,'||myemp.job||' ,'||v_sal);
             -- 将数据插入到test表中
             insert into test values(myemp.ename,myemp.sal,v_sal);
             num2 := num2+1;
              
         end if;
      end loop;
         dbms_output.put_line('统计符合MANAGER的个数:'||num1);
         dbms_output.put_line('统计符合SALESMAN的个数:'||num2);
      close v_emp;
    end;
    -- 创建test表
    create table test(
      Ename varchar2(30),
      Sal1 number,
      Sal2 number
    );
    View Code
  • 相关阅读:
    软件工程个人作业01
    个人冲刺——(五)
    个人冲刺——(四)
    个人冲刺——(三)
    个人冲刺——(二)
    个人冲刺——(一)
    单词统计
    第十周学习总结
    第九周学习总结
    用户模板场景分析
  • 原文地址:https://www.cnblogs.com/64Byte/p/12747110.html
Copyright © 2011-2022 走看看