3.9.2 语句级触发器
如果一个触发器在用户每次进行DML操作时被激发而且执行一次,而不管这个DML操作影响了多少行数据,这个触发器就是语句级触发器。
语句级触发器有前激发和后激发两种形式。前激发触发器是在DML操作执行之前被激发执行,后激发触发器是在DML操作执行之后被激发执行。无论是哪种形式,触发器都将执行一次。
例如,我们创建一个前激发触发器emp_trg,当用户对表EMP的DEPTNO列进行UPDATE操作时该触发器将被激发。创建该触发器的语句为:
CREATE TRIGGER emp_trg
BEFORE UPDATE OF deptno
ON emp
BEGIN
dbms_output.put_line('您正在修改表emp的deptno列');
END;
如果我们执行下面的UPDATE语句:
SQL>UPDATE emp set deptno=10 WHERE deptno=30;
那么可能得到如下结果:
您正在修改表emp的deptno列
已更新6行。
从UPDATE语句的执行结果可以看出,实际受影响的有6行数据,但是触发器只执行了一次。实际上不管这条语句影响了一行、两行还是多行,或者没有影响任何行,这个触发器都将在UPDATE语句执行之前被激发执行一次。再考虑下面的UPDATE语句,相信我们会对语句级触发器的执行有更深的理解。这次我们修改一个根本不存在的部门编号3。
SQL>UPDATE emp SET deptno=10 WHERE deptno=3;
您正在修改表emp的deptno列
已更新0行。
如果我们更关心用户对表所实施的访问本身,而不是该次访问影响的数据行数,这时我们可以在表上创建语句级触发器。
在触发器中可以使用三个条件谓词,这三个谓词用来判断当前所执行的操作。它们是:
·INSERTING:如果激发触发器的操作是INSERT,则结果为真,否则为假
·UPDATING:如果激发触发器的操作是UPDATE,则结果为真,否则为假
·DELETING:如果激发触发器的操作是DELETE,则结果为真,否则为假
这三个条件谓词通常作为IF语句的条件,用来判断用户当前所进行的操作。
如果要对用户在表emp上进行的所有DML操作进行监视,可以在这个表上创建一个触发器,将用户的所有DML操作作为日志记录下来。为此,我们先创建一个表emp_log,它的结构及各列的意义如表3-8所示。
然后,在表emp上创建一个后激发的触发器emp_dml_trg。只要用户在表上进行DML操作,这个触发器就会将执行这个操作的用户以及操作类型和操作时间记录在表emp_log中,而不管这样的操作影响了多少行数据。
CREATE OR REPLACE TRIGGER emp_dml_trg
AFTER
INSERT OR UPDATE OR DELETE
ON emp
DECLARE
dml_type char(10);
BEGIN
if INSERTING then
dml_type:='INSERT';
elsif UPDATING then
dml_type:='UPDATE';
elsif DELETING then
dml_type:='DELETE';
END if;
INSERT INTO emp_log
VALUES(user, dml_type, to_char(sysdate,'yyyy-mm-dd hh:mi:ss'));
END;
如果用户在表emp上进行了以下DML操作:
SQL>DELETE FROM emp WHERE deptno=20;
SQL>UPDATE emp set sal=sal+100;
SQL>INSERT INTO emp(empno, ename, job, deptno)VALUES(9999,'SMITH','SALES',20);
那么这三个操作的信息都将被记录在表emp_log中。查询表emp_log,将得到类似如下的结果:
SQL>SELECT*FROM emp_log;
OPER_USER OPER_TYPE OPER_TIME
SCOTT DELETE 2010-05-16 09:52:30
SCOTT UPDATE 2010-05-16 09:52:50
SCOTT INSERT 2010-05-16 09:53:50