觸發器可以看做一種“特殊”的存儲過程,它定義了一些與數據庫相關事件(INSERT,UPDATE,CREATE)發生時應執行的“功能代碼塊”,通常用於管理復雜的完整性約束,或監控對表的修改,或通知其他程序,甚至可以實現對數據的審計功能。
觸發事件:能夠引起觸發器運行的操作被稱為“觸發事件”,如執行DML(INSERT,UPDATE,DELETE),DDL(CREATE,ALTER.DROP);引發數據庫系統事件(系統啟動或退出,產生異常錯誤);引發用戶事件(登陸或退出數據庫操作)
根據觸發器的觸發事件和觸發器的執行情況,Oracle所支持的觸發器分為一下5種類型:
1行級觸發器:當DML語句對每一行數據進行操作時都會引起該觸發器的運行
2語句級觸發器:無論DML語句影響多上行數據,其所引起的觸發器僅執行一次
3替換觸發器:該觸發器是定義在視圖上的,而不是定義在表上,它是用來替換所使用實際語句的觸發器
4用戶事件觸發器:與DDL操作或用戶登陸、退出數據庫事件相關的觸發器。
5.系統事件觸發器:指Oracle數據庫系統的事件中進行觸發的觸發器,如Oracle實例的啟動與關閉
語句級觸發器:
例子:在SCOTT模式下,創建dept_log數據表,並在其中定義兩個字段,分別用來存儲操作種類信息和操作日期:
create table dept_log
(
operate_tag varchar2(10),
operate_tiem date
);
創建一個關於emp表的語句級觸發器,將用戶對dept表的操作信息保存到dept_log表中:
create or replace trigger tri_dept
before insert or update or delete
on dept
declare
var_tag varchar2(10);
begin
if inserting then
var_tag:='插入';
elsif updating then
var_tag:='修改';
elsif deleting then
var_tag:='刪除';
end if;
insert into dept_log
values(var_tag,sysdate);
end tri_dept;
/
執行觸發器,也就是觸發這些事件(insert,update,delete);之后再查看dept_log表就可以觀察到結果
行級觸發器:
例子 :在SCOTT模式下,創建一個用於存儲商品種類的數據表,其中包括商品序號列和商品名稱列:
create table goods(
id int primary key,
good_name varchar2(50));
創建一個序列:
create sequence seq_id;
創建一個觸發器,用於為goods表的id賦值
create or replace trigger tri_insert_good
before insert
on goods
for each row
begin
select seq_id.nextval
into :new.id
from dual;
end;
/
:new.id--列標識符
有兩種列標識符,
原值標識符:--:old.id --一般在update delete
新值標識符:--:new.id--一般在update insert
觸發該觸發器:
可以通過插入語句 insert into goods(good_name) values('蘋果');
同時用insert into goods(id,good_name)values (9,'葡萄');
然后再查詢該表即可知道是否,自動插入了id
但是第二條記錄的id,還是會順序增長,那是因為,觸發器將seq_id的nextval值賦給了:new.id,並且nextval屬性值是連續不間斷的
替換觸發器:
例子:首先創建一個視圖
(首先該用戶要有創建視圖的權限,切換到system ,grant create view to scott)
create view view_emp_dept
as
select empno,ename,dept.deptno,dname,job,hiredate from emp,dept
where emp.deptno=dept.deptno;
注意:在沒有創建“替換觸發器”時,試圖向該視圖中插入數據,是會有錯誤的ORA-01776:無法通過連接視圖修改多個基表
創建一個關於view_emp_dept視圖的替換觸發器,在該觸發器的主體中實現向emp表和dept表中插入兩行相互關聯的數據
create or replace trigger tri_insert_view
instead of insert
on view_emp_dept
for each row
declare
row_dept dept%rowtype;
begin
select * into row_dept from dept where deptno=:new.deptno;
if sql%notfound then
insert into dept(deptno,dname) values(:new.deptno,:new.dname);
end if;
insert into emp(empno,ename,deptno,job,hiredate) values
(:new.empno,:new.ename,:new.deptno,:new.job,:new.hiredate);
end tri_insert_view;
/
觸發該觸發器:
insert into view_emp_dept(empno,ename,deptno,dname,job,hiredate)
values(8888,'東方',10,'ACCOUTNTING','CASHIER',sysdate);
這樣,便可以插入一條記錄到視圖;
但是,如果這個deptno不在dept表中,那么會在dept表中插入相關記錄,但是,測試時,卻出現了錯誤

用戶事件觸發器:
因進行DDL操作或用戶登錄、退出操作而引起運行的一種觸發器,比如CREATE,ALTER,DROP,ANALYZE,COMMENT,GRANT,REVOKE,RENAME,TRUNCATE,SUSPEND,LOGON ,LOGOFF
創建一個日志信息表,用於保存DDL操作的信息,包括數據對象,數據對象類型,操作行為,操作用戶,操作日期
create table ddl_oper_log
(
db_obj_name varchar2(20),
db_obj_type varchar2(20),
oper_action varchar2(20),
oper_user varchar2(20),
oper_date date);
關於scott用戶的DDL操作(CREATE,ALTER,DROP),創建一個觸發器,然后將DDL操作的相關信息插入到ddl_oper_log日志表中
create or replace trigger tri_ddl_oper
before create or alter or drop
on scott.schema
begin
insert into ddl_oper_log values(
ora_dict_obj_name,--獲取DDL操作對象的名稱
ora_dict_obj_type,--獲取DDL操作所對應的數據庫對象的類型
ora_sysevent,--獲取觸發器的系統事件名稱
ora_login_user,--獲取登陸用戶名
sysdate);
end;
/
觸發觸發器:
create,alter,drop 然后再select * from ddl_oper_log;