Oracle SQL觸發器


一、觸發器
  觸發器是一個數據庫對象,是一個特殊的過程,當特定的時間發生時隱式地執行。比如在一個表中發生插入、更新或刪除的時間,或者 CREATE、ALTER 這樣的數據定義語句執行時,觸發器會隱式執行。當一些用戶行為或數據庫系統行為發生時(例如用戶登陸或數據庫關閉時),觸發器也會隱式執行。
  觸發器組成部分:
    觸發時間    觸發器體執行的時機    BEFORE、AFTER
    觸發事件    那類具體的數據操縱語句  INSERT、UPDATE、DELETE、CREATE、ALTER
    觸發器類型   觸發器體執行次數     Statement、Row
    觸發器體    觸發器執行的具體操作   PL/SQL 塊
【注意】:
當觸發器類型為 Statement 時,稱為語句觸發器,觸發器體對於觸發事件只執行一次,及時沒有行受到影響。
當類型為 Row 時,稱為行觸發器,觸發器體對受出發時間影響的每行執行一次

二、創建和測試語句觸發器
1.語法形式

CREATE [OR REPLACE] TRIGGER tname
   timing
   event1[OR event2 OR event3]
   ON table
trigger_body

  其中,tname 表示觸發器名字,timing 表示出發時間,event1、event2、event3 表示觸發事件,table 表示針對的表,trigger_body 表示觸發器體。

2.語句觸發器示例
  例如需要創建這樣一個觸發器,只能在周一到周五的 9:00 到 18:00 才可以針對部門表 departments 進行 DML 操作。

create or replace trigger dml_depts_time 
   before                                --在觸發事件發生前
   insert or update or delete      --觸發事件為增刪改
   on departments             --對表departments
begin                                                  --執行觸發器體
   if to_char(sysdate,'HH24:MI') not between '08:00' and '18:00' 
      or to_char(sysdate,'DY') in ('SAT','SUN') 
   then 
      raise_application_error(-20205,'You may only make changes during normal office hours');
   end if;
end dml_depts_time

  需要說明的是,上面創建觸發器的 SQL 語句中, RAISE_APPLICATION_ERROR 是一個內建過程,它返回一個錯誤給用戶,並導致 PL/SQL 塊失敗。當一個數據庫觸發器失敗時,觸發語句會自動回滾。
  編譯該觸發器,通過 PL/SQL Dev 查看 Triggers 文件夾,可以看到剛編譯的 dml_depts_time 觸發器。為了驗證觸發器是否可以使用,選擇在非工作時間,執行下面的 SQL 語句更新部門表的數據。

update departments
set department_name = 'IT GROUP'
where department_id = 60

結果

 

三、創建和測試行觸發器
1.語法形式

 CREATE [OR REPLACE] TRIGGER tname
     timing
     event1 [OR event2 OR event3]
     ON table
     [REFERENCING OLD AS old|NEW AS new]
     FOR EACH ROW
     [WHEN(condition)]
trigger_body

2.行觸發器示例
  例如需要創建一個行觸發器,當更改了雇員表中某行的職位編號字段或部門編號字段后,自動在職位變遷表 job_history 中增加一行記錄,記錄該雇員的職位(包括部門)變遷情況。創建行觸發器的 SQL 語句如下:

create or replace trigger update_job_history
   after                                        -- 在觸發事件發生后
   update of job_id,department_id         -- 觸發事件是修改職位或部門
   on employees                    --對表employ
   for each row                                      -- 對每行
begin                                                       --執行觸發器體
   insert into job_history(employee_id, start_date, end_date, job_id, department_id)
   values (:old.employee_id,:old.hire_date,sysdate,:old.job_id,:old.department_id);
end;

  編譯該觸發器。為了驗證該觸發器是否起作用,執行下面的 SQL 語句(更新兩行)並提交食物,打開職位變遷表 job_history , 自動增加了兩行記錄。

update employees
set department_id = 90
where employee_id in (106,107)

select * from hr.job_history

 四、小題
1.不允許刪除編號為7369的員工;

create or replace trigger nodelete_emp
    before
    delete 
    on scott.emp
    for each row
begin
    if :old.empno = 7369 then -- NEW 或 OLD 引用,不允許在表級觸發器中
       raise_application_error(-20006,'you can not delete the info .');
    end if ;
end ;

delete emp where empno = 7369;

結果

2.使用觸發器實現主鍵自增長;

create sequence seq  -- 創建序列
      increment by 1 -- 步長為1
      start with 20  -- 初始值為 20
      nomaxvalue     -- 無最大值
      nocycle        -- 不循環、

CREATE OR REPLACE TRIGGER add_auto_pk --創建自動增長 觸發器
  BEFORE 
  INSERT ON scott.emp
  FOR EACH ROW
DECLARE
  v_emp_no NUMBER(4);
BEGIN
  SELECT seq3.nextval INTO v_emp_no FROM dual; 
  :new.empno := v_emp_no;
END;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM