CREATE TRIGGER referential_integrity_checkBEFORE INSERT ON ReservesREFERENCING NEW AS NFOR EACH ROWWHEN ( NOT ( EXISTS (SELECT * FROM Sailors WHERE sid = N.sid) AND EXISTS (SELECT * FROM Boats WHERE bid = N.bid) ))ROLLBACK;
3. 行级 vs 语句级触发器
3.1 行级(FOR EACH ROW)
访问单条元组,比较 OLD / NEW
每条记录分别处理
CREATE TRIGGER NoLowerPricesAFTER UPDATE OF price ON ProductREFERENCING OLD AS O NEW AS NFOR EACH ROWWHEN (O.price > N.price)UPDATE ProductSET price = O.priceWHERE name = N.name;
3.2 语句级(FOR EACH STATEMENT)
一条语句影响多行时统一处理
NEW TABLE / OLD TABLE 只能用于语句级
CREATE TRIGGER insert_grade_checkAFTER INSERT ON enrollREFERENCING NEW TABLE AS NEFOR EACH STATEMENTINSERT INTO failedcourseSELECT *FROM NEWHERE grade < 3.0;
4. REFERENCING 子句
触发器类型
可用对象
行级
OLD, NEW
语句级
OLD TABLE, NEW TABLE
5. WHEN 子句要点
只负责判断是否执行动作
WHEN 中不能写修改语句
可省略
例:限制最多 10 次预约
CREATE TRIGGER notTooManyReservationsAFTER INSERT ON ReservesREFERENCING NEW AS NFOR EACH ROWWHEN (10 <= (SELECT COUNT(*) FROM Reserves WHERE sid = N.sid))DELETE FROM ReservesWHERE sid = N.sid AND day = ( SELECT MIN(day) FROM Reserves WHERE sid = N.sid );
6. 参照完整性常见模式
6.1 父表 DELETE → 拒绝
CREATE TRIGGER boats_deleteBEFORE DELETE ON BoatsREFERENCING OLD AS OFOR EACH ROWWHEN (EXISTS (SELECT * FROM Reserves WHERE bid = O.bid))ROLLBACK;
6.2 父表 DELETE → 级联删除
CREATE TRIGGER sailors_deleteAFTER DELETE ON SailorsREFERENCING OLD AS OFOR EACH ROWDELETE FROM ReservesWHERE sid = O.sid;
6.3 子表 UPDATE → 检查合法性
CREATE TRIGGER reserves_updateBEFORE UPDATE OF sid, bid ON ReservesREFERENCING NEW AS NFOR EACH ROWWHEN ( NOT ( EXISTS (SELECT * FROM Sailors WHERE sid = N.sid) AND EXISTS (SELECT * FROM Boats WHERE bid = N.bid) ))ROLLBACK;
7. Trigger vs CHECK / ASSERTION
项目
CHECK
ASSERTION
TRIGGER
作用范围
单表
多表
指定事件
是否过程化
否
否
是
是否动态
否
否
是
优化支持
高
高
低
8. 何时不建议用 Trigger
维护汇总数据 → 优先物化视图
数据复制 → 优先内置复制机制
级联执行风险高、影响关键事务性能
9. 常用模板汇总
模板 A:合法性检查
CREATE TRIGGER trigger_nameBEFORE INSERT OR UPDATE ON 表名REFERENCING NEW AS NFOR EACH ROWWHEN (不合法条件)ROLLBACK;
模板 B:插入后派生表(语句级)
CREATE TRIGGER trigger_nameAFTER INSERT ON 表名REFERENCING NEW TABLE AS NTFOR EACH STATEMENTINSERT INTO 目标表SELECT *FROM NTWHERE 条件;
模板 C:数量限制(动态约束)
CREATE TRIGGER trigger_nameAFTER INSERT ON 表名REFERENCING NEW AS NFOR EACH ROWWHEN ((SELECT COUNT(*) FROM 表名 WHERE 条件) >= 上限)DELETE FROM 表名WHERE ...;
模板 D:禁止不合理更新
CREATE TRIGGER trigger_nameAFTER UPDATE OF 列名 ON 表名REFERENCING OLD AS O NEW AS NFOR EACH ROWWHEN (O.列名 > N.列名)UPDATE 表名SET 列名 = O.列名WHERE 主键 = N.主键;
模板 E:子表插入 → 外键检查
CREATE TRIGGER trigger_nameBEFORE INSERT ON 子表REFERENCING NEW AS NFOR EACH ROWWHEN (NOT EXISTS (SELECT * FROM 父表 WHERE 主键 = N.外键))ROLLBACK;
模板 F:父表删除 → 拒绝删除
CREATE TRIGGER trigger_nameBEFORE DELETE ON 父表REFERENCING OLD AS OFOR EACH ROWWHEN (EXISTS (SELECT * FROM 子表 WHERE 外键 = O.主键))ROLLBACK;
模板 G:父表删除 → 级联删除
CREATE TRIGGER trigger_nameAFTER DELETE ON 父表REFERENCING OLD AS OFOR EACH ROWDELETE FROM 子表WHERE 外键 = O.主键;