触发器是一组存储在数据库里的 STORED PROCEDURE 单元,如果处于启用状态,能在特定事件发生时被自动执行。触发器在创建时,默认状态是启用状态,该状态可以手动禁用或启用。

    触发器的结构如下:

    1. TRIGGER trigger_name
    2. triggering_event
    3. [ trigger_restriction ]
    4. BEGIN
    5. triggered_action;
    6. END;

    在Oracle租户的 Schema 下,触发器名称(trigger_name)必须是唯一的。

    如果触发器是启用状态(enabled),triggering_event 语句会要求数据库在 trigger_restriction 条件为 TRUE 或者忽略时自动执行 triggered_action 语句。

    如果触发器状态是禁用状态(disabled),triggering_event 语句不会要求数据库自动执行 triggered_action 语句,即使 trigger_restriction 条件为 TRUE 或者忽略。

    跟子程序不同,触发器的执行逻辑不能被显式调用。触发器只能在处于启用状态时并且它定义的触发事件被触发时才会被调用。触发事件是可以通过用户或者应用的 SQL 触发,用户和应用可能都感知不到触发器在执行,除非触发器内部报异常了且没有被正确处理。

    一个简单的触发器的触发时机有四个点:

    • 在事件执行之前(语句级别的 BEFORE 触发器)
    • 在事件执行之后(语句级别的 AFTER 触发器)
    • 在每行被事件执行影响之前(行级的 BEFORE 触发器)
    • 在每行被事件执行影响之后(行级的 AFTER 触发器)

    一个 DML 语句可能会触发多个简单的触发器,触发执行顺序是:语句级 BEFORE 触发器 -> 行级 BEFORE 触发器 -> 行级 AFTER 触发器 -> 语句级 AFTER 触发器。同一类型的触发器的执行顺序是不确定的,当前暂不支持指定触发器执行顺序。

    使用触发器的一个用途是为了执行适用于所有客户端应用程序的业务规则。比如说,如果某个表有个时间列,业务要求插入的时间值必须不能早于当前时间。除了在应用程序里插入前做检查的方法外,还可以在数据库层面在表上定义一个基于 INSERT 和 UPDATE 事件的行级 BEFORE 触发器。在触发器中保证对该列的 INSERT 或 UPDATE 符合业务规则。这样做的好处就是没有客户端可以绕过这个业务规则约束,而不用修改每个客户端程序。