DML 触发器组成
本节主要介绍 DML 触发器的组成。
DML 触发器的组成
一个 DML 触发器通常由以下部分组成:
触发事件:引起触发器的事件。Vastbase 数据库支持 INSERT、UPDATE、DELETE、TRUNCATE 作为触发事件。
特别地,UPDATE 触发器可以进一步地设置为只针对 UPDATE 语句中 SET 子句指定的列触发。
触发类型:表示触发器是在事件执行前触发还是执行后触发。
- AFTER 触发器:触发器函数是在触发事件发生后执行。
约束触发器只能指定为 AFTER。
BEFORE 触发器:触发器函数是在触发事件发生前执行。
INSTEAD OF 触发器:使用触发器函数替代触发事件。INSTEAD OF 触发器创建在视图上,当对视图执行触发语句时自动触发。INSTEAD OF 触发器可以用来修改无法直接通过 DML 语句修改的视图。
关于触发器种类:
INSTEAD OF 触发器只能指定为
FOR EACH ROW
,并且只能在视图上定义。作用在视图上的 BEFORE 和 AFTER 触发器只能指定为
FOR EACH STATEMENT
。TRUNCATE 类型触发器只能指定为
FOR EACH STATEMENT
。
触发动作:触发器执行的动作,通常会执行一个 PL/pgSQL 函数。
触发对象:DML 触发器的触发对象包括表、视图和外表。
触发粒度:
FOR [EACH] { ROW | STATEMENT }
子句用于指定触发器的触发粒度。指定了
FOR EACH ROW
则表示创建行级触发器;指定FOR EACH STATEMENT
或不指定表示创建语句级触发器。例如,影响 10 行的 DELETE 将导致目标关系上的任何 ON DELETE触发器被分别调用 10 次,每次删除一次。相反,标记为 FOR EACH STATEMENT的触发器仅对任何给定操作执行一次,无论其修改多少行(特别是,修改零行的操作仍将导致执行任何适用的 FOR EACH STATEMENT 触发器)。
- 行级触发器:对于触发触发器的语句所修改的每一行都会调用一次触发器函数。
被行级触发器调用的触发器函数返回值可以考虑下列情形:
返回 NULL 表示跳过对当前行的操作,即执行器对一个特定表行的插入、修改或删除不执行调用触发器的行级操作。
对行级 INSERT 触发器和 UPDATE 触发器,返回值表示要被插入的行或被更新的行,这允许触发器函数修改它们。
- 语句级触发器:每语句的触发器对于其触发语句只被调用一次。
被语句级触发器调用的触发器函数应该总是返回 NULL。
触发条件:
WHEN
子句指定的逻辑表达式为 TRUE 时遇到触发事件才会自动执行触发器,使其执行触发操作。对于行级触发器,WHEN 条件可以检查该行的旧列值或新列值。
在 BEFORE 触发器中,WHEN 条件回在触发函数被执行前计算,因此使用 WHEN 条件与在触发器函数中的条件判断没有本质区别。
在 AFTER 触发器中,WHEN 条件会在行更新发生之后计算,该条件会决定事件是否被排队来触发该触发器。因此当 AFTER 触发器的 WHEN 不返回 TRUE 时,在语句的末尾没有必要将一个事件进行排队,也没有必要重新取出该行。如果触发器只对少数行触发,这可以使得修改很多行的语句明显加快。
INSTEAD OF 触发器不支持WHEN条件。
对于语句级触发器,由于条件不能引用表中的任何值,因此条件对于语句级触发器少有应用。
触发类型
BEFORE 与 AFTER 触发器
行级触发器和语句级触发器可以指定如下触发类型:
BEFORE ... FOR [EACH] STATEMENT
表示在触发语句执行之前。BEFORE ... FOR [EACH] ROW
表示在每行数据被触发语句修改之前。AFTER ... FOR [EACH] ROW
表示在每行数据被触发语句修改之后。AFTER ... FOR [EACH] STATEMENT
表示在触发语句执行之后。
对于语句级和行级触发器来说,BEFORE 触发器可以在对数据进行更改之前增强安全性并执行业务规则;AFTER 触发器则适合用来记录操作日志。
INSTEAD OF 触发器
INSTEAD OF 触发器只能在视图上定义,视图本质上不是可更新的,INSTEAD OF 触发器可以实现对视图的更新。
INSTEAD OF 触发器支持 WHEN 子句。
INSTEAD OF 触发器可以读取 OLD 和 NEW 值,但不能更改它们。
触发事件与类型组合
Vastbase 数据库支持的触发事件与类型的组合如下表所示。
表 1 支持的事件与类型组合的数据库对象