触发器里面before和after的区别

关键字before和after用于标识触发时间,顾名思义,before代表触发器里面的命令在DML修改数据之前执行,after代表触发器里面的命令在DML修改数据之后执行。

读者可以结合应用场景选择使用before或者after。

下面编者分别给出before和after的举例。

before举例:

在emp表上面创建触发器,当输入的工资小于100时,自动将工资修改为100。

create or replace trigger tri_emp_sal_check before INSERT OR UPDATE ON emp for each row BEGIN IF :new.sal <100 THEN :new.sal :=100; END IF; END;

执行DML语句

update emp set sal =90 where empno =3030;

commit;

发现工号3030员工的工资成功修改为100。

上面的触发器,我们尝试将before修改为after。编译的时候报错,不能通过。错误信息如下:

编者前面已经说过,after代表触发器里面的命令在DML修改数据之后执行,既然DML操作对数据的更改已经完成,当然不允许再修改new对象的属性值了,所以此处编译不通过。

after举例:

在emp表上面创建触发器,当修改员工工资时,记录日志。为了更明显的显示效果,编者在此触发器中使用了自治事务。并且在emp表的sal列上增加了check约束,限制sal的值大于等于100。

create or replace trigger tri_emp_sal_change after UPDATE ON emp for each row DECLARE V_ID NUMBER; pragma autonomous_transaction; BEGIN IF updating(SAL)THEN SELECT LOG_ID.NEXTVAL INTO V_ID FROM DUAL; insert into log (ID,CONTENT, IP, COMPUTERNAME) values (v_ID, :new.empno ||工资 ||由 || :old.sal ||变更为 || :new.sal, sys_context(userenv,ip_address), sys_context(userenv,terminal)); commit; END IF; END;

接着编者执行如下update命令

update emp set sal =90 where empno =3030;

报违反检查约束条件错误,如下图所示。

编者查看log表,发现log表为空。如下图所示。

说明使用after的情况下,触发器里面的命令在DML修改数据之后执行,此时log中无记录,是因为DML修改数据时违反检查约束条件,触发器里面的命令没有机会执行。

接着编者将触发器中的after替换成before。

执行相同的update命令

update emp set sal =90 where empno =3030;

同样违反检查约束条件,报错如下图所示。

编者接着查询log表,发现成功记录了修改日志。

说明使用before的情况下,触发器里面的命令在DML修改数据之前执行,此处虽然DML修改数据时违反检查约束条件,没有执行成功,但是由于触发器里面的命令先于DML修改数据之前执行,并且此处使用了自治事务,使得触发器里面的命令得以成功执行。

到底应该使用before还是after,要根据具体情况而定,一般需要更改要操作的数据时使用before。如果记录日志要使用after。只有使用了after才能确保DML语句成功执行,这样记录日志才有意义。

经验分享 程序员 微信小程序 职场和发展