轻松上手,快乐学习!

MySQL 教程

MySQL 首页MySQL 介绍MySQL 安装MySQL 实例库下载MySQL 实例库导入MySQL SELECTMySQL DISTINCTMySQL ORDER BYMySQL WHEREMySQL ANDMySQL ORMySQL INMySQL BETWEENMySQL LIKEMySQL LIMITMySQL IS NULLMySQL 别名MySQL JOINSMySQL INNER JOINMySQL LEFT JOINMySQL RIGHT JOINMySQL CROSS JOINMySQL SELF JOINMySQL GROUP BYMySQL HAVINGMySQL ROLLUPMySQL 子查询MySQL 派生表MySQL EXISTSMySQL CTEMySQL 递归 CTEMySQL UNIONMySQL INTERSECTMySQL MINUSMySQL INSERTMySQL INSERT INTO SELECTMySQL INSERT IGNOREMySQL UPDATEMySQL UPDATE JOINMySQL DELETEMySQL ON DELETE CASCADEMySQL DELETE JOINMySQL REPLACEMySQL PREPAREMySQL 事务MySQL 表锁定MySQL USEMySQL 数据库管理MySQL CREATE DATABASEMySQL DROP DATABASEMySQL 存储引擎MySQL CREATE TABLEMySQL 序列MySQL ALTER TABLEMySQL RENAME TABLEMySQL DROP COLUMNMySQL ADD COLUMNMySQL DROP TABLEMySQL 临时表MySQL TRUNCATE TABLEMySQL 数据类型MySQL NOT NULLMySQL Primary KeyMySQL Foreign KeyMySQL UNIQUEMySQL CHECKMySQL 字符集MySQL 排序规则MySQL 导入 CSVMySQL 导出 CSVMySQL 自然排序MySQL 基础

MySQL 存储过程

MySQL 存储过程介绍MySQL 存储过程实例MySQL 存储过程变量MySQL 存储过程参数MySQL 存储过程返回多值MySQL IF 语句MySQL CASE 语句MySQL IF CASE 选择MySQL 存储过程循环MySQL 存储过程游标MySQL 存储过程列表MySQL 存储过程异常处理MySQL SIGNAL 和 RESIGNALMySQL 存储函数

MySQL 视图

MySQL 视图教程SQL 视图介绍MySQL 视图介绍MySQL 创建视图MySQL 可更新视图WITH CHECK OPTIONLOCAL&CASCADEDMySQL 视图管理

MySQL 触发器

MySQL 触发器SQL 触发器MySQL 触发器介绍MySQL 触发器的创建MySQL 创建多个触发器MySQL 触发器管理MySQL 计划事件MySQL事件修改

MySQL 索引

MySQL 索引MySQL 索引创建MySQL 索引删除MySQL 显示索引MySQL 唯一索引MySQL 前缀索引MySQL 隐形索引MySQL 降序索引MySQL 复合索引MySQL 聚集索引MySQL 索引基数MySQL USE INDEXMySQL 强制索引

MySQL 管理

MySQL 管理MySQL访问控制系统MySQL 用户创建MySQL 用户密码MySQL 权限授予MySQL 权限撤销MySQL 角色MySQL 删除用户MySQL 表维护mysqldump 备份工具MySQL 数据库列表MySQL 表列表MySQL 表字段列表MySQL 用户列表MySQL 进程列表MySQL 列生成比较MySQL中同一表中的连续行

MySQL 全文搜索

MySQL 全文搜索MySQL 全文搜索介绍FULLTEXT索引MySQL 自然语言全文搜索MySQL 布尔全文搜索MySQL查询扩展MySQL ngram

MySQL 高级

MySQL 函数MySQL 窗口函数

MySQL 技巧

MySQL 查找重复数据MySQL 删除重复数据MySQL UUIDMySQL 表的复制MySQL 复制库MySQL 变量MySQL SELECT INTO 变量MySQL 表的存储引擎MySQL 使用正则查询MySQL 添加序号MySQL 随机查询MySQL 查询第 N 高记录MySQL 重置自增值MySQL VS MariaDBMySQL 间隔值MySQL 获取当天日期MySQL NULL 映射MySQL 注释理解MySQL EXPLAINMySQL 技巧介绍MySQL COUNTMySQL 数据分层MySQL 两表比较Mysql Like 优化

MySQL 窗口函数

MySQL CUME_DIST() 函数MySQL DENSE_RANK() 函数MySQL FIRST_VALUE 函数MySQL LAG() 函数MySQL LAST_VALUE() 函数MySQL LEAD 函数MySQL NTH_VALUE 函数MySQL NTILE 函数MySQL PERCENT_RANK 函数MySQL RANK 函数MySQL ROW_NUMBER 函数

MySQL 应用

MySQL应用程序编程接口PHP MySQL教程PHP 数据库连接

MySQL 优化

mysqld 内存持续变高


MySQL 创建多个触发器


简介:在本教程中,您将学习如何在MySQL中为相同的事件和操作时间创建多个触发器。

本教程与MySQL 5.7.2+版本相关。如果你有一个较旧版本的MySQL,教程中的语句将不起作用。

在MySQL 5.7.2版之前,您只能为表中的事件创建一个触发器,例如,您只能为BEFORE UPDATEAFTER UPDATE事件创建一个触发器。MySQL 5.7.2+解除了这一限制,允许您为表中的相同事件和操作时间创建多个触发器。事件发生时,触发器将按顺序激活。

创建第一个触发器的语法保持不变。如果您在表中有相同事件的多个触发器,MySQL将按创建顺序调用触发器。要更改触发器的顺序,您需要指定FOLLOWSPRECEDESFOR EACH ROW子句之后。

  •   FOLLOWS   选项允许在现有触发器之后激活新触发器。
  •   PRECEDES  选项允许在现有触发器之前激活新触发器。

以下是使用显式顺序创建新的附加触发器的语法:

DELIMITER $$
CREATE TRIGGER  trigger_name
[BEFORE|AFTER] [INSERT|UPDATE|DELETE] ON table_name
FOR EACH ROW [FOLLOWS|PRECEDES] existing_trigger_name
BEGIN
…
END$$
DELIMITER ;

MySQL多重触发器示例

让我们看一个在表中为同一事件和动作时间创建多个触发器的示例,以便更好地理解。

我们将使用示例数据库中products表进行演示。假设,每当我们更改产品(列)的价格时,我们都希望将旧价格记录在一个名为MSRPprice_logs的单独表中。

首先,我们使用CREATE TABLE语句创建一个price_logs新表,如下所示:

CREATE TABLE price_logs (
  id INT(11) NOT NULL AUTO_INCREMENT,
  product_code VARCHAR(15) NOT NULL,
  price DOUBLE NOT NULL,
  updated_at TIMESTAMP NOT NULL DEFAULT 
             CURRENT_TIMESTAMP 
             ON UPDATE CURRENT_TIMESTAMP,
  
  PRIMARY KEY (id),
  
  KEY product_code (product_code),
  
  CONSTRAINT price_logs_ibfk_1 FOREIGN KEY (product_code) 
  REFERENCES products (productCode) 
  ON DELETE CASCADE 
  ON UPDATE CASCADE
);

注意:如果在执行上面脚本时出现如下错误:ERROR 1215 (HY000): Cannot add foreign key constraint,请检查你创建的表的字符集与外键表的字符集是否一致,如果不一致改成一致再试试,我出现此问题原因是:默认字符为 latin1,而外键表为 utf8

其次,我们创建一个新的触发器,BEFORE UPDATEproducts表的事件发生时激活。触发器的名称是before_products_update

DELIMITER $$
CREATE TRIGGER before_products_update 
BEFORE UPDATE ON products 
FOR EACH ROW
BEGIN
	INSERT INTO price_logs ( product_code, price )
	VALUES(old.productCode, old.msrp);
END $$
DELIMITER ;

第三,我们使用以下UPDATE语句更改产品的价格并查询price_logs表:

UPDATE products
SET msrp = 95.1
WHERE productCode = 'S10_1678';
SELECT * FROM price_logs;
+----+--------------+-------+---------------------+
| id | product_code | price | updated_at          |
+----+--------------+-------+---------------------+
|  1 | S10_1678     |  95.7 | 2019-08-23 17:38:28 |
+----+--------------+-------+---------------------+
1 row in set (0.00 sec)

它按预期工作。

假设我们不仅希望看到旧价格以及何时更改,还要更改它。我们可以在price_logs表中添加其他列。但是,为了进行多个触发器演示,我们将创建一个新表来存储进行更改的用户的数据。新表的名称user_change_logs具有以下结构:

CREATE TABLE user_change_logs (
	id INT ( 11 ) NOT NULL AUTO_INCREMENT,
	product_code VARCHAR ( 15 ) DEFAULT NULL,
	updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
	updated_by VARCHAR ( 30 ) NOT NULL,
	PRIMARY KEY ( id ),
	KEY product_code ( product_code ),
	CONSTRAINT user_change_logs_ibfk_1 
	FOREIGN KEY ( product_code ) 
	REFERENCES products ( productCode ) 
	ON DELETE CASCADE 
	ON UPDATE CASCADE 
);

现在,我们创建第二个触发器,激活products表的 BEFORE UPDATE事件。此触发器将user_change_logs使用进行更改的用户的数据更新表。它在before_products_update触发后被激活。

DELIMITER $$
CREATE TRIGGER before_products_update_2 
BEFORE UPDATE ON products 
FOR EACH ROW FOLLOWS before_products_update 
BEGIN
	INSERT INTO user_change_logs ( product_code, updated_by )
	VALUES(old.productCode, USER ());
END $$
DELIMITER ;

我们来做快速测试吧。

首先,我们使用UPDATE语句更新产品价格,如下所示:

UPDATE products
SET msrp = 95.3
WHERE productCode = 'S10_1678';

其次,我们从两个表price_logsuser_change_logs表中查询数据:

SELECT * FROM price_logs;
+----+--------------+-------+---------------------+
| id | product_code | price | updated_at          |
+----+--------------+-------+---------------------+
|  1 | S10_1678     |  95.7 | 2019-08-23 17:38:28 |
|  2 | S10_1678     |  95.1 | 2019-08-23 17:46:28 |
+----+--------------+-------+---------------------+
2 rows in set (0.00 sec)
SELECT * FROM user_change_logs;
+----+--------------+---------------------+----------------+
| id | product_code | updated_at          | updated_by     |
+----+--------------+---------------------+----------------+
|  1 | S10_1678     | 2019-08-23 17:46:28 | root@localhost |
+----+--------------+---------------------+----------------+

如您所见,两个触发器都按预期顺序激活。


触发器顺序查看

如果使用SHOW TRIGGERS语句,则不会在表中看到针对相同事件和操作时序触发激活的顺序。

SHOW TRIGGERS FROM mysqldemo;

要查找此信息,您需要查询information_schema数据库triggers表中的action_order列,如下所示:

SELECT 
    trigger_name, action_order
FROM
    information_schema.triggers
WHERE
    trigger_schema = 'mysqldemo'
ORDER BY event_object_table , 
         action_timing , 
         event_manipulation
;
+--------------------------+--------------+
| trigger_name             | action_order |
+--------------------------+--------------+
| before_employee_update   |            1 |
| before_products_update   |            1 |
| before_products_update_2 |            2 |
+--------------------------+--------------+
3 rows in set (0.01 sec)

在本教程中,我们向您展示了如何在MySQL的表中为同一事件创建多个触发器。