• Oracle:简单SQL程序、存储过程、触发器


    /*
    以下代码是对emp表进行显示宽度设置
    */
    col empno for 9999;
    col ename for a10;
    col job for a10;
    col mgr for 9999;
    col hiredate for a12;
    col sal for 9999;
    col comm for 9999;
    col deptno for 99;
    col tname for a12;
    set pagesize 50;
     
    //------------------------------------------------------------------------------------------------------
     
    使用loop循环显示1-10【loop循环】
    declare
       --声明变量
       i number(2);
    begin
       i := 1;
       --以下代码是循环
       loop
         exit when i>10;
         dbms_output.put_line(i);
         i := i+1;
       end loop;
    end;
    /
     
    使用while循环显示10-20【while循环】
    declare
      i number(2) := 10;
    begin
      while i<=20
      loop
        dbms_output.put_line(i);
        i := i+1;
      end loop;
    end;
    /
     
    使用for循环显示20-30【for循环】
    declare
      i number;
    begin
      for i in 20..30
      loop
        dbms_output.put_line(i);
      end loop;
    end;
    /
     
    使用无参光标cursor,查询所有员工的姓名和工资【如果需要保存多行记录时,使用光标cursor】
    declare
       --定义一个cursor,里面装多条记录
       cursor cemp is select ename,sal from emp;
       --声明二个普通变量
       pename emp.ename%type;
       psal emp.sal%type;
    begin
       --打开cursor
       open cemp;
       --循环
       loop
         --将cursor下移,将用户名和工资存入二个自定义普通变量中
         fetch cemp into pename,psal;
         --判断是否该退出循环,切记
         exit when cemp%notfound;
         --显示
         dbms_output.put_line(pename||'的工资是'||psal);
       end loop;
       --关闭cursor
       close cemp;
    end;
    /
     
    使用无参光标,给员工涨工资,ANALYST涨1000,MANAGER涨800,其它涨400【编号,姓名,职位,薪水】
    declare
      cursor cemp is select empno,ename,job,sal from emp;
      pempno emp.empno%type;
      pename emp.ename%type;
      pjob emp.job%type;
      psal emp.sal%type;
    begin
      open cemp;
      loop
        fetch cemp into pempno,pename,pjob,psal;
        exit when cemp%notfound;
        --if是PLSQL
        if pjob='ANALYST' then
           --update是SQL
           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;
      commit;
      close cemp;
    end;
    /
     
    使用带参光标,查询20号部门的员工姓名和工资,工资都加800
    declare
      --定义一个带参cursor
      cursor cemp(pdeptno number) is select empno,ename,sal from emp where deptno=pdeptno;
      pename emp.ename%type;
      psal emp.sal%type;
      pempno emp.empno%type;
    begin
      --打开光标,同时传入实际参数
      open cemp(20);
      loop
         fetch cemp into pempno,pename,psal;
         exit when cemp%notfound;
         update emp set sal=sal+800 where empno=pempno;
      end loop;
      --关闭光标
      close cemp;
    end;
    /
     
    set serveroutput on
    /*
     * 输入部门号,显示对应部门号中总员工数, 和每个员工的姓名和工资信息。
     */
    declare
      -- 光标
      cursor c_emp(dno number) is select ename, sal from emp where deptno=dno;
      vname emp.ename%type;
      vsal emp.sal%type;
      vcount number;
      vdeptno dept.deptno%type; -- 用于保存接收到的部门编号信息
    begin
      -- 得到查询的条件
      vdeptno := &input_deptno;
     
      -- 显示部门中的总员工数
      select count(*) into vcount from emp where deptno=vdeptno;
      dbms_output.put_line( '总人数为: ' || vcount );
     
      -- 显示每一个员工的姓名与工资信息
      open c_emp(vdeptno);
      loop
        fetch c_emp into vname, vsal;
        exit when c_emp%notfound;
       
        dbms_output.put_line( ' ' || vname || ' 的工资为: ' || vsal );
       
      end loop;
      close c_emp;
    end;
    /
     
    oracle系统内置例外,被0除异常【zero_divide】
    declare
      i number;
      s number;
    begin
      i := 10;
      s := i/0;
    exception
      when zero_divide then
           dbms_output.put_line('自已捕获系统内置例外');
    end;
    /
     
    用户自定义例外,没有找到员工例外【no_emp_found】
    declare
      cursor cemp(pempno number) is select ename from emp where empno=pempno;
      pename emp.ename%type;
      --声明自定义例外
      no_emp_found exception;
    begin
      open cemp(1111);
      loop
        fetch cemp into pename;
        --如果没有找到员工
        if cemp%notfound then
           --抛例外
           raise no_emp_found;
        end if;
      end loop;
      close cemp;
    exception
      when no_emp_found then
           dbms_output.put_line('查无此员工');
    end;
    /
     
    //------------------------------------------------------------------------------------------------------
     
    创建无参存储过程hello,无返回值
     
    create or replace procedure hello
    as
    begin
       dbms_output.put_line('这就是存储过程');
    end;
    /
     
    删除存储过程hello
    drop procedure hello;
     
    调用存储过程方式一【exec 存储过程名】
    exec hello;
     
    调用存储过程方式二【PLSQL程序】
    begin
      --调用存储过程
      hello;
    end;
    /
     
    调用存储过程方式三【JDBC】
    CallableStatement
     
    创建有参存储过程raiseSalary(编号),为7369号员工涨10%的工资,并显示出涨前和涨后的工资【演示in的用法,默认in】
    create or replace procedure raiseSalary(pempno number)
     
     
    as
      --as看作declare,但不能出现declare,声明变量
      psal emp.sal%type;
    begin
      --查询编码为7369号员工的工资
      select sal into psal from emp where empno=pempno;
      --显示
      dbms_output.put_line('7369号员工涨前工资'||psal);
      dbms_output.put_line('7369号员工涨后工资'||psal*1.1);
    end;
    /
    exec raiseSalary(7369);
     
     
    创建无参存储函数myshow,有返回值
    create or replace function myshow return varchar2
    as
    begin
       return '哈哈';
    end;
    /
     
    删除存储函数myshow
    drop function myshow;
     
    调用存储函数方式一【PLSQL程序】
     
    declare
      value varchar2(6);
    begin
      value := myshow();
      --value := myshow;可以
      dbms_output.put_line(value);
    end;
    /
     
    调用存储函数方式二【JDBC】
    CallableStatement
     
    创建有参存储函数findEmpIncome(编号),查询7369号员工的年收入【演示in的用法,默认in】
     
     
    create or replace function findEmpIncome(pempno in number) return number
    as
       --年收入
       income number;
    begin
       select sal*12+NVL2(comm,comm,0) into income from emp where empno=pempno;
       --返回年收入
       return income;
    end;
    /
     
    declare
       income number;
    begin
       income := findEmpIncome(7369);
       dbms_output.put_line('年收入是'||income);
    end;
    /
     
    创建有参存储函数findEmpNameAndSal(编号),查询7902号员工的的姓名和月薪,【返回多个值,演示out的用法】
    当返回2个或多个值,必须使用out符号
    当返回1个值,就无需out符号
     
    create or replace function findEmpNameAndSal(pempno in number,pename out varchar2) return number
    as
      psal emp.sal%type;
    begin
      select ename,sal into pename,psal from emp where empno=pempno;
      --返回月薪
      return psal;
    end;
    /
     
    ---------------------------------------相互转值
     
    declare
       psal emp.sal%type;
       pename emp.ename%type;
    begin
       psal := findEmpNameAndSal(7902,pename);
       dbms_output.put_line('7902号员工的姓名'||pename||',薪水是'||psal);
    end;
    /
     
    创建有参存储过程findEmpNameAndSalAndJob(编号),查询7902号员工的的姓名,职位,月薪【演示out的用法】
    create or replace procedure
    findEmpNameAndSalAndJob(pempno in number,pename out varchar2,pjob out varchar2,psal out number)
    as
    begin
       select ename,job,sal into pename,pjob,psal from emp where empno=pempno;
    end;
    /
     
    declare
        pename emp.ename%type;
        pjob emp.job%type;
        psal emp.sal%type;
    begin
        findEmpNameAndSalAndJob(7902,pename,pjob,psal);
        dbms_output.put_line('7902号员工的姓名是'||pename||':'||pjob||':'||psal);
    end;
    /
     
    什么情况下使用存储过程?什么情况下使用存储函数?
    项目中的原则:
    A)如果只有一个返回值:用函数
    B)如果无返回值,或超过1个以上的返回值,用过程
       
    创建语句级触发器insertEmpTrigger,当对emp表进行insert操作前,显示"hello world"
    create or replace trigger insertEmpTrigger
    before
    insert
    on emp
    begin
      dbms_output.put_line('插入记录之前执行');
    end;
    /
     
    删除触发器insertEmpTrigger
    drop trigger insertEmpTrigger;
     
    使用insert语句操纵表,引起触发器工作
    insert into emp(empno,ename,job,sal) values(1122,'JACK','IT',5000);
     
    insert into emp
    select *
    from new_emp;
     
    创建语句级触发器deleteEmpTrigger,当对emp表进行delete操作后,显示"world hello"
    create or replace trigger deleteEmpTrigger
    after
    delete
    on emp
    begin
      dbms_output.put_line('删除记录之后执行');
    end;
    /
     
    周一到周五,且9-17点能向数据库插入数据,否则【raise_application_error('-20000','例外原因')】
     
    分析:
       A)周六,周日 不管何时 不能插入数据
       B)周一到周五 9-17之外,不包括9和17点,不能插入数据
    create or replace trigger securityEmpTrigger
    before
    insert
    on emp
    declare
       pday varchar2(9);
       phour number(2);
    begin
       select to_char(sysdate,'day') into pday from dual;
       --隐式将varchar2转成number
       select to_char(sysdate,'hh24') into phour from dual;
       --判断
       if (pday in ('星期六','星期日')) or (phour not between 9 and 17) then
          --抛例外,该例是系统的
          raise_application_error('-20999','不是工作时间,不能操作数据库');
       end if;
    end;
    /
     
    -- 是否是工作时间
    -- to_char(sysdate, 'hh24')
    -- to_number( to_char(sysdate, 'hh24') )
    -- not (to_number( to_char(sysdate, 'hh24') ) between 9 and 17)
    -- 阻止继续执行
    -- raise_application_error(-20000, '现在是非工作时间,不能插入数据!')
     
    create or replace trigger mytrigger
    before insert
    on emp2
    declare
      -- 变量
    begin
      if not (to_number( to_char(sysdate, 'hh24') ) between 9 and 17) then
        raise_application_error(-20000, '现在是非工作时间,不能插入数据!');
      end if;
    end;
    /
       
    创建行级触发器,涨后工资这一列,确保大于涨前工资【for each row/:new.sal/:old.sal】
     
    create or replace trigger checkSalaryTrigger
    after
    update of sal
    on emp
    for each row
    begin
       --如果更新后的值<更新前的值
       if :new.sal < :old.sal then
          --抛例外
          raise_application_error('-20888','工资不能越涨越低');
       end if;
    end;
    /
     
    update emp set sal=sal+1 where ename='SMITH';
     
    错误编号的范围:[20000-20999]
    如欢如殇 授以青春鲜活肢体奔忙 如思如忘 驱以老朽深沉灵魂冥想 始自情热激荡 从未敢终于世事炎凉 无能执手相望 无法去尝试结发同床 无力至心死身僵 一息坚强 ------ 我一直没有放弃,如果你也能看到 修身 修禅
  • 相关阅读:
    关于通胀,交易手续费和加密货币的货币政策
    私有链和联盟链的机会与挑战
    耶鲁大学公开课:博弈论第九节(笔记)
    区块链匿名技术
    区块链对比数据库
    硬盘 分区 格式化 和挂载
    Nginx实战系列之功能篇----后端节点健康检查
    Nginx实战系列之功能篇----后端节点健康检查
    Nginx实战系列之功能篇----后端节点健康检查
    Nginx实战系列之功能篇----后端节点健康检查
  • 原文地址:https://www.cnblogs.com/lz2lhy/p/6845055.html
Copyright © 2020-2023  润新知