觸發器
- 觸發器組成
1、觸發事件
DML或DDL語句。
2、觸發時間
是在觸發事件發生之前(before) 還是之后(after) 觸發
3、觸發操作
使用PL/SQL塊進行相應的數據庫操作
4、觸發對象
表、視圖、模式、數據庫
5、觸發頻率
觸發器內定義的動作被執行的次數,包括語句級和行級ji。
- 限制
1、觸發器不接受參數
2、一個表上最多可有12個觸發器,但同一時間、同一事件、同一類型的觸發器只能有一個。並各觸發器之間不能有矛盾。
3、一個表上的觸發器越多,該表上的DM操作的性能影響就越大
4、觸發器代碼的大小不能超過32K。如需要大量的代碼創建觸發器,則首先創建過程,然后在觸發器中使用CALL語句調用過程
5、觸發器代碼只能包含SELECT、INSERT、UPDATE和DELETE語句,
6、不能包含DDL語句(CREATE、ALTER和DROP) 和事務控制語句(COMMIT、ROLLBACK和SAVEPOINT)
- 創建dml觸發器
語句觸發器
1、語句觸發器是指當執行DML語句時被隱含執行的觸發器
2、如果在表上針對某種DML操作創建了語句觸發器,則當執行DML操作時會自動地執行觸發器的相應代碼
3、為了審計DML操作,或者確保DML操作安全執行時,可以使用語句觸發器
觸發器用途很多,例如用戶清算購物車后將會觸發待收貨的數據庫
代碼示例:
--創建觸發器
create or replace trigger tri_test
before--觸發之前
update or delete--更新或刪除
on emp for each row--對行進行操作 begin dbms_output.put_line(:old.sal);--old表示數據庫舊值 insert into demo(id) values (:new.sal);--new新值 end; update emp set sal=888 where empno=7788; commit; --代碼解釋:先執行創建觸發器代碼后,再執行最后的更新語句。當更新恩平、表后將會輸出數據庫中本來存放的值,並且觸發添加語句在demo表中插入一條語句。
自定義異常,觸發器 攔截
簡單代碼示例1:
-- 觸發器 攔截
create or replace trigger tri_test
before
update or delete
on emp for each row begin if to_char(sysdate,'yyyy-mm-dd')='2018-03-13' then--將系統日期轉化為字符類型 -- 自定義異常, raise_application_error(-20000,'今天不能修改數據');-- 負20000之前的異常都已經被定義 end if; end; update emp set sal=777 where empno=7788; commit; --觸發器創建后,執行最后代碼,將會有異常提示:今天不能修改數據
示例2:
create or replace trigger tri_test
before
update or delete or insert
on emp for each row begin case when updating then raise_application_error(-20000,'今天不能修改'); when inserting then raise_application_error(-20001,'今天不能插入'); when deleting then raise_application_error(-20000,'今天不能刪除'); end case; end; update emp set sal=777 where empno=7788; insert into emp (empno) values (123); commit;
- 創建替代(instead of)觸發器
一般語法:
create or peplace trigger 觸發器名稱
instead of
操作條件on視圖名稱
for each row(因為instead of 觸發器只能在行級上出發,所以沒有必要指定)
begin
操作條件from 表名where 列名= :old.列名;
end;
其中:
instead of 選項使oracle 激活觸發器,而不是執行觸發器。只能對視圖和對象視圖建立 instead of觸發器,而不能對表、模式和數據庫建立instead of 觸發器。
總結創建替代觸發器的過程:
- 為用戶授權
- 創建視圖
- 創建觸發器
- 執行條件
簡答代碼示例:
------ 替換觸發器創建過程示例 -- 授權 grant create view to scott; -- 創建視圖 create view emp_view as select deptno,count(*) total,sum(sal) total_salary from emp group by deptno; --創建觸發器 create trigger emp_view_delete instead of delete on emp_view for each row begin delete from emp where deptno= :old.deptno; end; --執行條件 delete from emp_view where deptno=10; select * from emp; rollback;
上述代碼中最后 rollback的意思為回滾,和commit用法相反,當不確定要刪除數據庫中的數據時使用rollback意味着撤回,用commit執行dml語句后,數據庫將做出永久改變。
總結替代觸發器創建特點:
- 只能被創建在視圖上,並且該視圖沒有指定的with check option選項
- 不能被指定before和after選項
- for each row語句是可選的
- 沒有必要針對一個表的視圖上創建替代觸發器,只要創建dml觸發器就可以了
案例
使用觸發器實現自動編號
對於表中id自動遞增在sql語句中可以用序列來實現,下面是用觸發器來實現自動編號;
思路:
- 創建表
- 創建序列
- 創建觸發器
- 執行條件
代碼如下:
--使用觸發器實現自動編號 --創建序列 create sequence stu_seq start with 1 increment by 1 --創建觸發器 create or replace trigger tri_stu before insert on student for each row begin select stu_seq.nextval into :new.id from dual; end; --執行條件 insert into student (id,name) values(1,'lwx'); commit;