触发器是特殊形式的存储过程,在执行修改数据的查询时自动执行。只要参照完整性和其它声明性约束不足够,就可以使用触发器。触发器事件
可以对以下一种或多种触发事件定义触发器:
操作 | 说明 |
---|---|
INSERT | 只要有新行插入到与触发器关联的表中,就调用触发器。 |
DELETE | 只要删除了关联表中的行,就调用触发器。 |
UPDATE | 只要更新了关联表中的行,就调用触发器。 |
UPDATE OF column-list | 只要更新了关联表中的行,且修改了 column-list中的列,就调用触发器。 |
您可以为需要处理的每个事件分别编写触发器,或者,如果您有一些共享操作以及一些取决于事件的操作,您可以为所有事件创建触发器并使用 IF 语句区分所发生的操作。触发器是特殊形式的存储过程,在执行修改数据的查询时自动执行。只要参照完整性和其它声明性约束不足够,就可以使用触发器
触发时间
触发器可以是行级别或语句级别:
-
行级别触发器为更改的每一行执行一次。行级别触发器在更改行之前或之后执行。
-
语句级别触发器在整个触发语句完成后执行。
示例 1:行级别 INSERT 触发器
以下触发器是行级别 INSERT 触发器的示例。它检查为新雇员输入的出生日期是否合理:
CREATE TRIGGER check_birth_date AFTER INSERT ON Employee REFERENCING NEW AS new_employee FOR EACH ROW BEGIN DECLARE err_user_error EXCEPTION FOR SQLSTATE '99999'; IF new_employee.birth_date > 'June 6, 2001' THEN SIGNAL err_user_error; END IF; END
此触发器在将任何行插入 employee 表之后触发。它检测并且不允许对应于出生日期晚于 2001 年 6 月 6 日的任何新行。
短语 REFERENCING NEW AS new_employee 使用别名 new_employee 以允许触发器代码中的语句引用新行中的数据。
发出错误将导致撤消触发语句以及该触发器之前执行的任何操作的结果。
对于将许多行添加到 employee 表的 INSERT 语句,check_birth_date 触发器为每一新行触发一次。如果该触发器对任何行触发失败,则 INSERT 语句的所有结果都回退。
您可以通过将示例的第一行更改为以下内容,指定触发器在插入行之前而非插入行之后触发:
CREATE TRIGGER mytrigger BEFORE INSERT ON Employee
REFERENCING NEW 子句引用该行的插入的值;它与触发器的计时(之前或之后)无关。
您会发现,在某些情况下,使用声明参照完整性或 CHECK 约束(而不是触发器)实施约束会更容易。例如,使用列检查约束实施上例已证实效率更高并且更简明:
CHECK (@col <= 'June 6, 2001')
示例 2:行级别 DELETE 触发器示例
以下 CREATE TRIGGER 语句定义行级别 DELETE 触发器:
CREATE TRIGGER mytrigger BEFORE DELETE ON employee REFERENCING OLD AS oldtable FOR EACH ROW BEGIN ... END
REFERENCING OLD 子句使用别名 oldtable 使删除触发器代码能够引用所删除的行中的值。
您可以通过将示例的第一行更改为以下内容,指定触发器在删除行之后而非删除行之前触发:
CREATE TRIGGER check_birth_date AFTER DELETE ON employee
REFERENCING OLD 子句与触发器的计时(之前或之后)无关。
示例 3:语句级别 UPDATE 触发器示例
以下 CREATE TRIGGER 语句适合于语句级别 UPDATE 触发器:
CREATE TRIGGER mytrigger AFTER UPDATE ON employee REFERENCING NEW AS table_after_update OLD AS table_before_update FOR EACH STATEMENT BEGIN ... END
REFERENCING NEW 和 REFERENCING OLD 子句允许 UPDATE 触发器代码引用所更新的行的旧值和新值。表别名 table_after_update 引用新行中的列,表别名 table_before_update 引用旧行中的列。
对于语句级别触发器和行级别触发器,REFERENCING NEW 和 REFERENCING OLD 子句在意义上稍有不同。对于语句级别触发器,REFERENCING OLD 或 NEW 别名是表别名,而在行级别触发器中,它们引用所变更的行。
-
执行触发器
只要对触发器中指定的表执行了 INSERT、UPDATE 或 DELETE 操作,触发器就会自动执行。行级别触发器为受影响的每一行触发一次,而语句级别触发器则为整个语句触发一次。
在 INSERT、UPDATE 或 DELETE 触发触发器时,操作的顺序如下所示:
-
在触发器触发前。
-
执行参照操作。
-
执行操作本身。
-
在触发器触发后。
如果其中任何步骤遇到在过程或触发器内未处理的错误,则前面的步骤被撤消,不执行随后的步骤,触发触发器的操作将失败。
删除触发器 (SQL):
-
连接到数据库。
-
执行 DROP TRIGGER 语句。
示例
以下语句从数据库中删除 mytrigger 触发器:
DROP TRIGGER mytrigger
触发器执行权限
您不能授予执行触发器的权限,因为用户不能执行触发器:Adaptive Server Anywhere 触发它们以响应对数据库执行的操作。不过,触发器确实具有与它所执行的操作关联的权限,并且定义其权限以执行某些操作。
触发器使用定义了这些权限的表的所有者的权限(而不是导致触发器触发的用户的权限,并且不是创建该触发器的用户的权限)执行。
在触发器引用表时,它使用表创建者的组成员资格找到没有指定的显式所有者名称的表。例如,如果 user_1.Table_A 上的触发器引用 Table_B,并且没有指定 Table_B 的所有者,那么,Table_B 就必须已经由 user_1 创建,或者,user_1 必须(直接或间接地)是作为 Table_B 的所有者的某个组的成员。如果这两个条件都不具备,该触发器触发时将出现消息 [没有找到表]。
此外,user_1 必须具有执行该触发器中指定的操作的权限。
-