一:概念
触发器是一种特殊的存储过程,不接受参数,由事件调用
二:分类
1.DML触发器:创建在表上,由dml事件触发
2.instead of触发器:替代触发器,oracle8专门用来处理视图。创建在视图上且只能在行级上触发
3.DDL触发器: 数据库对象的创建和修改触发
4.系统触发器:数据库系统事件触发 如启动与关闭
三:触发器组成
l 触发事件:引起触发器被触发的事件。 例如:DML语句(INSERT, UPDATE, DELETE语句对表或视图执行数据处理操作)、DDL语句(如CREATE、ALTER、DROP语句在数据库中创建、修改、删除模式对象)、数据库系统事件(如系统启动或退出、异常错误)、用户事件(如登录或退出数据库)。
l 触发时间:即该TRIGGER 是在触发事件发生之前(BEFORE)还是之后(AFTER)触发,也就是触发事件和该TRIGGER 的操作顺序。
l 触发操作:即该TRIGGER 被触发之后的目的和意图,正是触发器本身要做的事情。 例如:PL/SQL 块。
l 触发对象:包括表、视图、模式、数据库。只有在这些对象上发生了符合触发条件的触发事件,才会执行触发操作。
l 触发条件:由WHEN子句指定一个逻辑表达式。只有当该表达式的值为TRUE时,遇到触发事件才会自动执行触发器,使其执行触发操作。
l 触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。
语句级(STATEMENT)触发器:是指当某触发事件发生时,该触发器只执行一次;
行级(ROW)触发器:是指当某触发事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次。
四:注意事项
l 触发器不接受参数。
l 一个表上最多可有12个触发器,但同一时间、同一事件、同一类型的触发器只能有一个。并各触发器之间不能有矛盾。
l 在一个表上的触发器越多,对在该表上的DML操作的性能影响就越大。
l 触发器最大为32KB。若确实需要,可以先建立过程,然后在触发器中用CALL语句进行调用。
l 在触发器的执行部分只能用DML语句(SELECT、INSERT、UPDATE、DELETE),不能使用DDL语句(CREATE、ALTER、DROP)。
l 触发器中不能包含事务控制语句(COMMIT,ROLLBACK,SAVEPOINT)。因为触发器是触发语句的一部分,触发语句被提交、回退时,触发器也被提交、回退了。
l 在触发器主体中调用的任何过程、函数,都不能使用事务控制语句。
l 在触发器主体中不能申明任何Long和blob变量。新值new和旧值old也不能是表中的任何long和blob列。
l 不同类型的触发器(如DML触发器、INSTEAD OF触发器、系统触发器)的语法格式和作用有较大区别。
五:触发器执行顺序
1. 执行 BEFORE语句级触发器;
2. 对与受语句影响的每一行:
l 执行 BEFORE行级触发器
l 执行 DML语句
l 执行 AFTER行级触发器
3. 执行 AFTER语句级触发器
六:触发器限制
l CREATE TRIGGER语句文本的字符长度不能超过32KB;
l 触发器体内的SELECT 语句只能为SELECT … INTO …结构,或者为定义游标所使用的SELECT 语句。
l 触发器中不能使用数据库事务控制语句 COMMIT; ROLLBACK, SVAEPOINT 语句;
l 由触发器所调用的过程或函数也不能使用数据库事务控制语句;
l 触发器中不能使用LONG, LONG RAW 类型;
l 触发器内可以参照LOB 类型列的列值,但不能通过 :NEW 修改LOB列中的数据;
七:语法
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER }
{INSERT | DELETE | UPDATE [OF column [, column …]]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
ON [schema.]table_name | [schema.]view_name
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ]
[WHEN condition]
八:简单的例子
1.基本语法
create or replace trigger tr_del
before delete --删除前触发
on scott.emp
for eachrow--行级别触发器
2.限制非工作时间操作表
create or replace trigger tr_dept
before insert or delete or update
on dept
begin
if(to_char(sysdate,'day')in('星期六','星期日'))or(to_char(sysdate,'HH24:mi')not between '08:30'and'18:00') then
raise_application_error(-20001,'不是上班时间,不能修改dept表');
end if;
end;
本文内容来自
http://blog.youkuaiyun.com/indexman/article/details/8023740/
https://www.cnblogs.com/wishyouhappy/p/3665851.html