数据库原理与应用 第 16 章 · 第二节
课程 › 第 16 章 › 第二节 语法例题 1例题 2例题 3 版式
第 16 章 触发器和事件 · 第二节

创建触发器

CREATE TRIGGER 的语法,NEW 与 OLD,三个例题
本 节 知 识 点
  1. 05创建触发器的语法
  2. 06例题 1:空成绩置 0
  3. 07例题 2:修改时记日志
  4. 08例题 3:删除时级联删除
05
第 16 章 · 第二节 · 课件第 9、10、11、12 页合并重做

创建触发器的语法

时机、事件、表,加上 FOR EACH ROW 和触发器体。

16.1 MySQL 触发器课件第 10、11、12 页合并

创建触发器的语法

CREATE [DEFINER = 用户] TRIGGER 触发器名 触发时机 触发事件 ON 表名 FOR EACH ROW [触发顺序] 触发器体
部分说明
触发时机BEFORE 或 AFTER
触发事件INSERT、UPDATE 或 DELETE,一个触发器只响应一种
FOR EACH ROW行级触发,语句影响几行就执行几次
触发顺序同一表、同一时机、同一事件有几个触发器时,用 FOLLOWS 或 PRECEDES 指定先后
触发器体一条语句,或 BEGIN … END 语句块
NEW 与 OLD
事件NEWOLD
INSERT将要插入的行没有
UPDATE修改后的行修改前的行
DELETE没有被删除的行
  • 用 NEW.列名、OLD.列名 访问这一行的值
  • 只有 BEFORE 触发器可以修改 NEW.列名
  • 查看用 SHOW TRIGGERS,删除用 DROP TRIGGER,没有修改触发器的语句

试一试三种事件中的 NEW 与 OLD

事件
sno第二列第三列

实 验

实验 1-3 用错 NEW 与 OLD

06
第 16 章 · 第二节 · 课件第 13、14 页合并重做

例题 1:空成绩置 0

BEFORE INSERT,在写入之前修改 NEW.score。

16.1 MySQL 触发器课件第 13、14 页合并

例题 1:空成绩置 0

建立触发器 insert_sc_trigger:向 sc 表插入成绩为空的记录时,把成绩设置为 0,不为空时按给定的值插入。
建立触发器
DELIMITER $$
CREATE TRIGGER insert_sc_trigger
BEFORE INSERT ON sc
FOR EACH ROW
BEGIN
  IF NEW.score IS NULL THEN
    SET NEW.score = 0;
  END IF;
END $$
DELIMITER ;
验证
INSERT INTO sc
VALUES ('s2', 'c8', NULL);
SELECT * FROM sc WHERE sno = 's2';
snocnoscore
s2c470.00
s2c557.00
s2c681.50
s2c7NULL
s2c80.00
07
第 16 章 · 第二节 · 课件第 15、16、17 页合并重做

例题 2:修改时记日志

AFTER UPDATE,把 OLD 和 NEW 的值记入日志表。

16.1 MySQL 触发器课件第 15、16、17 页合并

例题 2:修改时记日志

建立触发器 update_s_trigger:修改学生的专业时,把修改时间和修改前后的专业记入 update_s_log 表。
日志表和触发器
CREATE TABLE update_s_log (
  sno CHAR(5) NOT NULL,
  sn VARCHAR(10) NOT NULL,
  omaj VARCHAR(100) NOT NULL,
  nmaj VARCHAR(100) NOT NULL,
  udate DATETIME(0) NOT NULL
);
DELIMITER $$
CREATE TRIGGER update_s_trigger
AFTER UPDATE ON s
FOR EACH ROW
BEGIN
  INSERT INTO update_s_log
  VALUES (OLD.sno, OLD.sn, OLD.maj,
          NEW.maj, NOW());
END $$
DELIMITER ;
验证
UPDATE s SET maj = '计算机'
WHERE sno = 's2';
SELECT * FROM update_s_log
WHERE sno = 's2';
snosnomajnmaj
s2苏乐信息计算机
  • OLD.maj 是修改前的专业,NEW.maj 是修改后的专业
  • UPDATE 找到几行就记几行,专业没有变化也记。只记真正的修改,要加 IF OLD.maj <> NEW.maj
08
第 16 章 · 第二节 · 课件第 18、19 页合并重做

例题 3:删除时级联删除

BEFORE DELETE,先删成绩,再删学生。

16.1 MySQL 触发器课件第 18、19 页合并

例题 3:删除时级联删除

建立触发器 delete_s_trigger:删除 s 表中某个学生的记录时,同时删除 sc 表中这个学生所有课程的成绩。
建立触发器
DELIMITER $$
CREATE TRIGGER delete_s_trigger
BEFORE DELETE ON s
FOR EACH ROW
BEGIN
  DELETE FROM sc
  WHERE sc.sno = OLD.sno;
END $$
DELIMITER ;
验证
DELETE FROM s WHERE s.sno = 's1';
SELECT * FROM s;
SELECT * FROM sc;
  • s 中没有了 s1,sc 中 s1 的两门成绩也被删除
  • OLD.sno 是被删除的学生的学号
这里必须用 BEFORE。sc 的 sno 参照 s,删除 s1 这一行时 sc 中如果还有它的成绩,外码约束报错 1451,AFTER 触发器来不及执行。

试一试删除 s1 时的执行顺序

触发器
次序做什么结果

实 验

实验 1-6 删除学生时删除成绩

保山学院·人工智能教研室·曹鼎鼎