1. 程式人生 > >二十一、Oracle學習筆記:編寫函式和觸發器

二十一、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;