- 1 MySQL 简介
- MySQL 版本和产品线说明
- MySQL 安装
- 2 MySQL 基础教程
- 2.1 SQL 语法:SELECT/INSERT/UPDATE/DELETE
- 2.2 MySQL 列类型
- 2.3 使用用户变量
- 2.4 MySQL 的日期和时间管理
- 2.5 集合运算
- 3 MySQL 高级教程
- 3.1 触发器
- 3.2 视图
- 3.3 复制 Replication~主从库配置
- 3.4 分区存储
- 本章参考
- 4 MySQL 优化
- 4.1 优化数据库结构
- 4.2 优化 SQL 语句
- 4.3 优化索引
- 4.4 优化数据库服务器 mysql_serverd
- 4.5 修改配置文件 my.cnf/my.ini
- 5 MySQL 管理
- 5.1 MySQL 管理常用命令
- 5.2 MySQL 权限管理
- 5.3 MySQL 备份和恢复
- 5.4 MySQL 数据库安全
- 常见问题 FAQ
- 使用的常见问题
- MySQL 字符集乱码
- MySQL 存储二进制图片
- 参考资料
3.1 触发器
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论