今天周六,早上去了趟花卉市场。
草色侵大路,花枝出苑墙。
草长莺飞二月天,该春游了。
关于表中的DML触发器,到上次为止已经叙述了他们的很基本用法,我们今天介绍一下关于行触发器的另外一个重要的功能:
BEFORE的行触发来更新列值的变更。也就是说,行触发器是在对象行上启动的,但是对于BEFORE的行触发器,
如果我们手工修改“:NEW.列名”的值,会发生什么情况呢?告诉大家我么直接可以修改这个值,也就直接修改了该行的列的值。
(在AFTER的行触发器中进行相同赋值时,会发生编译错误。道理可以想象得到。)
下面介绍一下这个类似的例子:
表中有2列:“登录日”和“最终更新日”,INSERT的时候,“登录日”设置成当前的日期时间(SYSDATE),
UPDATE的时候,“最终更新日”设置为当前的日期时间(SYSDATE)。
这2个值得更新是通过行触发器发生的。
以下是代码的例子:
首先,建立一张表“TEST01”,其中有登录日和最终更新日2列。
SQL> CREATE TABLE TEST01
2 ( A NUMBER,
3 登录日 DATE,
4 最终更新日 DATE)
5 /
为表创建一个触发器:
1 CREATE OR REPLACE TRIGGER TEST01_TRIG
2 /******************************************************************/
3 --设定登录日(INSERT)或最终更新日(UPDAATE)的触发器
4 /*****************************************************************/
5 BEFORE INSERT OR UPDATE
6 ON TEST01
7 FOR EACH ROW --<----指定行触发器
8 BEGIN
9 IF INSERTING THEN --INSERT时
10 :NEW.登录日:=SYSDATE; --给 :NEW.登录日赋值
11 ELSE --UPDATE时
12 :NEW.最终更新日:=SYSDATE; -给 :NEW.最终更新日赋值
13 END IF;
14 END;
SQL> /
触发器已创建。
该触发器启动时点:对TEST01表某一行数据进行INSERT或UPDATE操作之前BEFORE的时候触发的。
第9行:「INSERTING」,判断操作属于INSERT。 类似的也可以通过 “UPDAATING”和“DELETING”判断各自操作类型。
具体逻辑:INSERT的时候给“:NEW.登录日”赋值;其他的时候给“:NEW.最终更新日”赋值。赋的值是SYSDATE。
我们来确认一下执行结果:
首先,INSERT2行数据:
SQL> INSERT INTO TEST01(A) VALUES (1);
创建了一行。
SQL> INSERT INTO TEST01(A) VALUES (2);
创建了一行。
修改系统的DATE类型的日期格式,以便能显示出时分秒。
SQL> ALTER SESSION SET NLS_DATE_FORMAT=‘YY/MM/DD HH24:MI:SS’;
会话已更改。
查询TEST01表:
SQL> SELECT * FROM TEST01;
A 登录日 最终更新日
-------------------------------------------------------
1 21/03/06 14:12:10
2 21/03/06 14:12:19
这样没有使用UPDATE语句,就可以设置登录日了。
那么,接下来针对A=1这一行,进行UPDATE。
SQL> UPDATE TEST01 SET A = 1 WHERE A = 1;
一行已更新。
然后查询一下结果,A=1行的最终更新日被设定了。
SQL> SELECT * FROM TEST01;
A 登录日 最终更新日
-------------------------------------------------------------------
1 21/03/06 14:12:10 21/03/06 14:12:51
2 21/03/06 14:12:19
这样,那个行什么时候被INSERT的,什么时候被UPDAATE的,就自动被记录了。
假如在这里,将登录日列和最终更新日列作为更新对象时会怎么样呢?使我们登录或者更新得值呢,还是触发器里边的值呢?
让我么试一下:
SQL> UPDATE TEST01
2 SET 最终更新日 = TO DATE(“2021/12/31”,“YYYY/MM/DD’)
3 WHERE A = 2;
一行已更新。
SQL> SELECT * FROM TEST01;
A 登录日 最终更新日
--------------------------------------------------------------
1 21/03/06 14:12:10 21/03/06 14:12:51
2 21/03/06 14:12:19 21/03/06 14:13:22 ←这一行的最终更新日不是我们主动跟新的值,而是触发器里边的值
如,对于A=2行,我们目的是想将最终更新日列更新为2021/12/31,但最终更新日是更新时间的SYSDATE值。
结论就是,在BEFORE的行触发器中,如果对“:NEW.列名”进行赋值,即使在该列中指定不同的值进行DML操作,也会强制使用触发器里边的赋给的值。
这就是我们要注意的细节。本次到此为止。