触发器(Trigger)是用户定义在关系表上的一类由事件驱动的特殊过程。一旦定义,任何用户对表的增、删、改操作均由服务器自动激活相应的触发器。它类似于约束,但是比约束更加灵活,并且可以实施比FOREIGN KEY(外键)约束、CHECK约束更为复杂的检查和操作,具有更精细和更强大的数据控制能力。 下面是触发器一些特性:
1、 表的创建者才可以在表上创建触发器,并且一个表上只能创建一定数量的触发器;
2、 触发器名可以包含模式名,也可以不包含。但是在同一模式下,触发器必须是唯一的,并且触发器名和表名必须在同一模式下;
3、 当某个表的数据发生变化时,将激活定义在该表上相应的“触发事件”的触发器,因此,该表也称为触发器的目标表;
4、 触发事件可以是单独的操作(增、删、改)或几个操作的组合,如INSERT OR DELETE等。而且UPDATE后边还可以有OF<触发列,…..>,即进一步指明修改哪些列时激活触发器;
5、 触发器的类型,按所触发动作的间隔尺寸可以分为行级触发器(FOR EACH ROW)和语句级触发器(FOR EACH STATEMENT)。对于什么叫“间隔尺寸”,书面上比较难理解,那么看以下的例子:
例:假设有个职工工资表WORKER,要求每个职工的应发工资不能低于3000元。那么如果在这个表上创建了一个AFTER UPDATE触发器,且该表有1000行记录,执行如下语句:
UPDATE WORKER SET Deptno=5; 如果改触发器为语句级触发器,那么执行完该语句后,触发动作只发生一次。如果是行级触发器,触发动作将执行将执行1000次;
6、 触发条件,当触发器被激活时,只有当触发条件为真时触发动作体才执行。如果省略WHEN触发条件,则触发动作体在触发器被激活后无条件执行;
7、 触发动作体既可以是一个匿名PL/SQL过程块,也可以是对已创建存储过程的调用。如果是行级触发器,在两种情况下,用户都能在过程体中使用NEW和OLD引用UPDATE/INSERT事件之后的新值和UPDATE/INSERT事件之后的旧值。如果是语句级触发器,则不能在触发动作体中使用NEW或OLD进行引用。
如果触发动作体执行失败,激活触发器的事件就会终止执行,触发器的目标表或触发器可能影响的其他对象不会发生任何变化。 以下是两个个经典的触发器例子: 例1:定义一个BEFORE行级触发器,为职工表WORKER定义完整性规则“管理人员工资不能低于4000元,如果低于4000元,自动改为4000元”。
CREATE TRIGGER insert_Or_Updatee_Sal /*在WORKER表中定义触发器*/ BEFORE INSERT OR UPDATE ON WORKER /* 触发事件是插入或更新操作*/ FOR EACH ROW /*表示行级触发器*/ AS BEGIN /*定义触发器动作体,这是一个PL/SQL过程块*/ IF(new.Job=’管理人员’)AND(new.Sal<4000)THEN /*因为是行级触发器*/ new.Sal := 4000; /*过程体中使用插入或更新操作后的新值*/ END IF; END;
例2:定AFFTER行级触发器,当员工表WORKER的工资发生变化后就自动在工资变化表Sal_log中增加一条记录。 首先建立工资变化表Sal_log: CREATE TABLE Sal_log (Eno NUMERIC(4) REFERENCES WORKER(Eno), Sal NUMERIC(7,2), Username char(10), Date TIMESTAMP );
CREATE TRIGGER Insert _Sal AFTER INSERT ON WOEKER FOR EACH ROW AS BEGIN INSERT INTO Sal_log VALUES( new.Eno,new.Sal,CURRENT_USER,CURRENT_TIMESTAMP); END; CREATE TRIGGER Update _Sal AFTER INSERT ON WOEKER FOR EACH ROW AS BEGIN IF(new.Sal<>old.Sal) THEN INSERT INTO Sal_log VALUES( new.Eno,new.Sal,CURRENT_USER,CURRENT_TIMESTAMP); END IF; END;
|