返回介绍

3.1 触发器

发布于 2024-10-03 00:33:41 字数 3851 浏览 0 评论 0 收藏 0

MySQL 5.1 包含对触发程序的支持。触发程序是与表有关的命名数据库对象,当表上出现特定事件时,将激活该对象。例如,下述语句将创建 1 个表和 1 个 INSERT 触发程序。触发程序将插入表中某一列的值加在一起:

mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
  -> FOR EACH ROW SET @sum = @sum + NEW.amount;

触发器操作语句

  • 查询触发器:SHOW TRIGGERS [FROM schema_name];
  • 删除触发器:DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name
  • 创建触发器:CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW trigger_stmt

触发器创建语句
CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW trigger_stmt
其中:

  • trigger_name:标识触发器名称,用户自行指定;
  • trigger_time:标识触发时机,取值为 BEFORE 或 AFTER;
  • trigger_event:标识触发事件,取值为 INSERT、UPDATE 或 DELETE;
  • tbl_name:标识建立触发器的表名,即在哪张表上建立触发器;
  • trigger_stmt:触发器程序体,可以是一句 SQL 语句,或者用 BEGIN 和 END 包含的多条语句。

由此可见,可以建立 6 种触发器,即:BEFORE INSERT、BEFORE UPDATE、BEFORE DELETE、AFTER INSERT、AFTER UPDATE、AFTER DELETE。

另外有一个限制是不能同时在一个表上建立 2 个相同类型的触发器,因此在一个表上最多建立 6 个触发器。

INSERT 型触发器:插入某一行时激活触发器,可能通过 INSERT、LOAD DATA、REPLACE 语句触发;

UPDATE 型触发器:更改某一行时激活触发器,可能通过 UPDATE 语句触发;

DELETE 型触发器:删除某一行时激活触发器,可能通过 DELETE、REPLACE 语句触发。

BEGIN … END 详解

在 MySQL 中,BEGIN … END 语句的语法为:

BEGIN
 [statement_list]
 END

NEW 与 OLD 详解

上述示例中使用了 NEW 关键字,和 MS SQL Server 中的 INSERTED 和 DELETED 类似,MySQL 中定义了 NEW 和 OLD,用来表示触发器的所在表中,触发了触发器的那一行数据。

具体地:

  • 在 INSERT 型触发器中,NEW 用来表示将要(BEFORE)或已经(AFTER)插入的新数据;
  • 在 UPDATE 型触发器中,OLD 用来表示将要或已经被修改的原数据,NEW 用来表示将要或已经修改为的新数据;
  • 在 DELETE 型触发器中,OLD 用来表示将要或已经被删除的原数据;
  • 使用方法: NEW.columnName (columnName 为相应数据表某一列名)
  • 另外,OLD 是只读的,而 NEW 则可以在触发器中使用 SET 赋值,这样不会再次触发触发器,造成循环调用

触发器的执行顺序

我们建立的数据库一般都是 InnoDB 数据库,其上建立的表是事务性表,也就是事务安全的。这时,若 SQL 语句或触发器执行失败,MySQL 会回滚事务,有:

  • 如果 BEFORE 触发器执行失败,SQL 无法正确执行。
  • SQL 执行失败时,AFTER 型触发器不会触发。
  • AFTER 类型的触发器执行失败,SQL 会回滚。

IF 表达式:

  • IF(expr1,expr2,expr3) 按顺序返回不为 NULL 的一个。
  • IFNULL(expr1,expr2) 默认结果值为两个表达式中更加 通用 的一个(非 NULL 值),顺序为 STRING、 REAL 或 INTEGER

流程控制语句:IF/ELSEIF/ELSE

IF search_condition THEN
  statement_list

[ELSEIF search_condition THEN]
  statement_list ...

[ELSE
  statement_list]

END IF

示例一:

delimiter //
create trigger InsertUser
before insert on user
for each row
Begin
insert into user_group(uid,gid) values(new.uid,'group4444444444');
end; //
delimiter ;

示例二

delimiter //
create trigger InsertUser
before insert on user
for each row
Begin
IF new.Type=2 then
insert into user_group(uid,gid) values(new.uid,'group4444444444');
else
insert into user_group(uid,gid) values(new.uid,'group55555555555')
END IF;
end;//
delimiter ;

示例三:

delimiter //
create trigger InsertUser
before insert on user
for each row
Begin
IF new.room_classify_b!=''  THEN
  -- do nothing --
set @tmp=1;
ELSEIF new.type=1 then
insert into user_group(uid,gid) values(new.uid,'578d3369633b47bd9c1fe8bf905cbfb1');
END IF;
IF new.type=2 then
 insert into user_group(uid,gid) values(new.uid,'387bcd57fc5a4c3c9de83ee210fef661');
END IF;
end;//
delimiter ;

常见错误提示:

mysql update new row is not allow in after trigger

解释:如果本表 INSERT 插入一行时,对本表的另一字段值进行修改,需要用到 BEFORE 而不能用 AFTER。UPDATE 时对本表的另一字段值进行修改,也只能用 BEFORE。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文