2、触发器的类型有:
触发器类型:
1、 语句触发器
2、 行触发器
3、INSTEAD OF触发
4、 系统条件触发器
5、 用户事件触发器
2.1、语句级触发器.(语句级触发器对每个DML语句执行一次)
是在表上或者某些情况下的视图上执行的特定语句或者语句组上的触发器。能够与INSERT、UPDATE、DELETE或者组合上进行关联。但是无论使用什么样的组合,各个语句触发器都只会针对指定语句激活一次。比如,无论update多少行,也只会调用一次update语句触发器。
实例:
createorreplacetriggertri_test
afterinsertorupdateordeleteontest
begin
ifupdatingthen
dbms_output.put_line('修改');
elsifdeletingthen
dbms_output.put_line('删除');
elsifinsertingthen
dbms_output.put_line('插入');
endif;
end;
2.2、行级触发器.(行级触发器对DML语句影响的每个行执行一次)
实例一:
触发器
(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)行级触发器
createtabletest(sidnumber,snamevarchar2(20));--创建一个表
createsequenceseq_test;--创建序列
createorreplacetriggertri_test--创建触发器
beforeinsertorupdateofsidontest
foreachrow--触发每一行
begin
ifinsertingthen
selectseq_test.nextvalinto:new.sidfromdual;
else
raise_application_error(-20020,'不允许更新ID值!');--中断程序
endif;
end;
测试,插入几条记录
insertintotestvalues(0,'ff');
insertintotestvalues(0,'ff');
insertintotestvalues(0,'tt');
实例二:
创建一个触发器,无论用户插入新记录,还是修改emp表的job列,都将用户指定的job列的值转换成大写.
createorreplacetriggertrig_job
beforeinsertorupdateofjob
onemp
foreachrow
begin
ifinsertingthen
:new.job:=upper(:new.job);
else
:new.job:=upper(:new.job);
endif;
end;
2.3、instead of触发器.
(此触发器是在视图上而不是在表上定义的触发器,它是用来替换所使用实际语句的触发器.)
语法如下:
createorreplacetriggertrig_test
insteadofinsertorupdateon表名
referencingnewasn
foreachrow
declare
..........
begin
........
end;
2.4、模式触发器.
可以在模式级的操作上建立触发器.
实例如下:
createorreplacetriggerlog_drop_obj
afterdroponschema
begin
insertinto.....
end;
2.5、数据库级触发器.
可以创建在数据库事件上的触发器,包括关闭,启动,服务器错误,登录等.这些事件都是实例范围的,不与特定的表或视图关联.
实例:
createorreplacetriggertrig_name
afterstartupondatabase
begin
...........
end;
2.6、例子:
需要对在表上进行DML操作的用户进行安全检查,看是否具有合适的特权。
Createtablefoo(anumber);
Createtriggerbiud_foo
Beforeinsertorupdateordelete
Onfoo
Begin
Ifusernotin(‘DONNY’)then
Raise_application_error(-20001,‘Youdon’thaveaccesstomodifythistable.’);
Endif;
End;
/
即使SYS,SYSTEM用户也不能修改foo表
2.7、[试验]
对修改表的时间、人物进行日志记录。
1、 建立试验表
createtableemployees_copyasselect*fromhr.employees
2、 建立日志表
createtableemployees_log(
whovarchar2(30),
whendate);
3、 在employees_copy表上建立语句触发器,在触发器中填充employees_log表。
Createorreplacetriggerbiud_employee_copy
Beforeinsertorupdateordelete
Onemployees_copy
Begin
Insertintoemployees_log(Who,when)
Values(user,sysdate);
End;
/
4、 测试
updateemployees_copysetsalary=salary*1.1;
select*fromemployess_log;
5、 确定是哪个语句起作用?
即是INSERT/UPDATE/DELETE中的哪一个触发了触发器?
可以在触发器中使用INSERTING / UPDATING / DELETING条件谓词,作判断:
begin
ifinsertingthen
-----
elsifupdatingthen
-----
elsifdeletingthen
------
endif;
end;
ifupdating(‘COL1’)orupdating(‘COL2’)then
------
endif;
2.8、[试验]
1、 修改日志表
altertableemployees_log
add(actionvarchar2(20));
2、 修改触发器,以便记录语句类型。
then
l_action:=’Delete’;
else
raise_application_error(-20001,’Youshouldneverevergetthiserror.’);
Insertintoemployees_log(Who,action,when)
Values(user,l_action,sysdate);
End;Createorreplacetriggerbiud_employee_copy
Beforeinsertorupdateordelete
Onemployees_copy
Declare
L_actionemployees_log.action%type;
Begin
ifinsertingthen
l_action:=’Insert’;
elsifupdatingthen
l_action:=’Update’;
elsifdeleting
/
3、测试
insertintoemployees_copy(employee_id,last_name,email,hire_date,job_id)
values(12345,’Chen’,’Donny@hotmail’,sysdate,12);
select*fromemployees_log