二十一、Oracle学习笔记:编写函数和触发器

 

一、函数或过程的选择
    1.如果要进行DML(增删改),选择存储过程
    2.如果没有DML,选择函数
   

二、函数

1.格式

  create or replace function 函数名(参数1 类型,参数2 类型, 。。。)
  return 类型
  is
    --变量声明区
  begin
    --业务逻辑区
  return 值;
  end;
  /

2.实例

--练习,山寨sign函数:
--逻辑:判断某一个数,如果>0,就返回1,
--如果<0,返回-1,如果=0,就返回0;
  create or replace function sgn(a number)
  return number
  is
  begin
    if a>0 then
      return 1;
    elsif a=0 then
      return 0;
    else 
       return -1;
    end if;
   end;
   /

--select sgn(5) from dual;
  declare
    res number;
  begin
    res:=sgn(10);
      if res>0 then
        dbms_output.put_line('正数');
      end if;
  end;  
  / 

--练习:比较两个员工的工资高低
  create or replace function sgnsal(id1 number,id2 number)
  return number
  is
    sal1 number;
    sal2 number;
  begin
    select sal into sal1 from emp where empno=id1;
    select sal into sal2 from emp where empno=id2;
    if sal1>sal2 then
           return 1;
    elsif sal1=sal2 then
      return 0;
    else 
      return -1;
    end if;
  end;
  /

  declare
    res number;
  begin
    res:=sgnsal(7369,7788);
    if res=1 then
      dbms_output.put_line('前面的大');
    elsif res=0 then
      dbms_output.put_line('一样大');
    else 
      dbms_output.put_line('后面的大');
    end if;
  end;
  /
      
      
--练习:根据部门号计算部门的总工资
  create or replace function total(dno number)
  return number
  is
    totalsal number;
  begin
    select sum(sal) into totalsal from emp where deptno=dno;
    return totalsal;
   end;
  /    
  select total(10) from dual;  

函数的参数类型也和存储过程一样规则

--练习:返回两个数a,b的和,并返回这两个数
  create or replace function abtotal(a in out number,b in out number)
  return number
  is
  begin
    if a is null then
      a:=1;
    end if;
    if b is null then
      b:=1;
    end if; 
    return a+b;
   end;
   /
        
  declare
    total number;
    a number;
    b number:=10;
  begin
    total:=abtotal(a,b);
    dbms_output.put_line(total);
    dbms_output.put_line(a);
    dbms_output.put_line(b);
  end; 
  /       


      
      
三、触发器
1.定义:是ORACLE在发生某些事件时,可以自动触发并调用的PLSQL程序,可以定义在事件上,由事件自动触发。
2.分类:
 (1)系统触发器
       由系统时间触发的PLSQL程序,比如登录ORACLE\登出ORACLE
 (2)DML触发器
       由DML语句触发的PLSQL程序,如增删改
     
3.DML触发器
(1)语句级触发器
   如果执行完一条DML语句后,希望对整张表的数据进行预算,使用语句级触发器, 这种触发器是在DML执行前/执行后触发的。

--格式:
--注意:触发器是自己调用的,不需要调用
  create or replace trigger 触发器名
  before|after  insert|update|delete on 表
  declare
    声明变量
  begin
    处理业务
  end;
  /
--练习:在进行任何增删改操作后,计算出员工数,员工总薪资,员工平均工资
  create or replace trigger mmp
  after insert or update or delete on emp
  declare
    countEmp number;
    totalSal number;
    avgSal number;
  begin
    select count(*),sum(sal),trunc(avg(sal),2) into countEmp,totalSal,avgSal from emp;
    dbms_output.put_line('总人数  '||countEmp);
    dbms_output.put_line('总工资  '||totalSal);
    dbms_output.put_line('平均工资'||avgSal);
  end;
  /
  update emp set sal=2500 where empno=7369;
  drop trigger mmp;


 (2)行级触发器
      如果在执行DML时,希望对当前操作的数据进行处理,那么可以使用行级触发器,行级触发器也是在执行DML之前/之后自动触发的,在行级触发器中可以使用行变量,引用到DML所操作的数据,这个行变量是内置的,可以直接使用。
      行变量
          :new 表示引用的是新增后的行数据
          :old 表示引用的是修改/删除前的行数据
      规则
          insert语句只有:new,表示插入后的新数据
          delete语句只有:old,表示删除前的旧数据
          update语句既有:new也有:old,其中
          :new表示修改后的数据,
          :old表示修改前的数据

--格式:
  create or replace trigger 触发器名
  before|after insert|update|delete on 表
  for each row
  declare
    声明变量
  begin
    处理业务
   end;
   /
       
--用法:
--变量名.字段名
--触发器中不能写commit

 

--练习:删除dept表数据之前,将删除记录存入备份表中
  create or replace trigger tri_dept
  before delete on dept 
  for each row
  declare
  begin
    insert into dept_bak values(:old.deptno,:old.dname,:old.loc);
  end;
  /    
  delete from dept;
  select * from dept_bak;
  rollback;
       
--练习:修改员工工资,显示一下之前和之后的工资
  set serveroutput on; 
  create or replace trigger tri_sal
  after update on emp 
  for each row
  declare
  begin
    dbms_output.put_line('old='||:old.sal||',new='||:new.sal);
  end;   
  /   
  update emp set sal=4000 where empno=7369;  

 

你可能感兴趣的:(Oracle学习笔记)