创建多个触发器
简介:在本教程中,您将学习如何为具有相同事件和动作时间的表创建多个触发器。
本教程与MySQL版本5.7.2+相关。
如果您使用的是旧版本的MySQL,则本教程中的语句将无效。
在MySQL 5.7.2之前的版本中,您只能为表中的事件创建一个触发器,例如,您只能为BEFORE UPDATE或AFTER UPDATE事件创建一个触发器。
MySQL 5.7.2+取消了此限制,并允许您为给定的表创建具有相同事件和动作时间的多个触发器。
当事件发生时,这些触发器将顺序激活。
以下是用于定义将在现有触发器之前或之后激活以响应相同事件和动作时间的触发器的语法:
DELIMITER $$ CREATE TRIGGER trigger_name {BEFORE|AFTER}{INSERT|UPDATE|DELETE} ON table_name FOR EACH ROW {FOLLOWS|PRECEDES} existing_trigger_name BEGIN -- statements END$$ DELIMITER ;
使用此语法,FOLLOWS或PRECEDES指定是应在现有触发器之前还是之后调用新触发器。
FOLLOWS允许新触发器在现有触发器之后激活。
PRECEDES允许新触发器在现有触发器之前激活。
MySQL多重触发器的例子
我们将使用样本数据库中的产品表进行演示。
假设您要更改产品的价格(MSRP列),并将旧价格记录在名为PriceLogs的单独表中。
首先,使用以下CREATE TABLE语句创建一个新的price_logs表:
CREATE TABLE PriceLogs ( id INT AUTO_INCREMENT, productCode VARCHAR(15) NOT NULL, price DECIMAL(10,2) NOT NULL, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), FOREIGN KEY (productCode) REFERENCES products (productCode) ON DELETE CASCADE ON UPDATE CASCADE );
其次,创建一个新触发器,该触发器将在products表的BEFORE UPDATE事件发生时激活:
DELIMITER $$ CREATE TRIGGER before_products_update BEFORE UPDATE ON products FOR EACH ROW BEGIN IF OLD.msrp <> NEW.msrp THEN INSERT INTO PriceLOgs(product_code,price) VALUES(old.productCode,old.msrp); END IF; END$$ DELIMITER ;
第三,检查产品S12_1099的价格:
SELECT productCode, msrp FROM products WHERE productCode = 'S12_1099';
第三,使用以下UPDATE语句更改产品的价格:
UPDATE products SET msrp = 200 WHERE productCode = 'S12_1099';
第四,从PriceLogs表中查询数据:
SELECT * FROM PriceLogs;
它按预期工作。
假设您要记录更改价格的用户。
为此,您可以在PriceLogs表中添加其他列。
但是,出于演示多个触发器的目的,我们将创建一个新的单独的表来存储进行更改的用户的数据。
第五,创建UserChangeLogs表:
CREATE TABLE UserChangeLogs ( id INT AUTO_INCREMENT, productCode VARCHAR(15) DEFAULT NULL, updatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, updatedBy VARCHAR(30) NOT NULL, PRIMARY KEY (id), FOREIGN KEY (productCode) REFERENCES products (productCode) ON DELETE CASCADE ON UPDATE CASCADE );
第六,为产品表创建一个BEFORE UPDATE触发器。
此触发器在before_products_update触发器之后激活。
DELIMITER $$ CREATE TRIGGER before_products_update_log_user BEFORE UPDATE ON products FOR EACH ROW FOLLOWS before_products_update BEGIN IF OLD.msrp <> NEW.msrp THEN INSERT INTO UserChangeLogs(productCode,updatedBy) VALUES (OLD.productCode,USER()); END IF; END$$ DELIMITER ;
让我们进行一次快速测试。
第七,使用以下UPDATE语句更新产品的价格:
UPDATE products SET msrp = 220 WHERE productCode = 'S12_1099';
第八,从PriceLogs和UserChangeLogs表中查询数据:
SELECT * FROM PriceLogs;
SELECT * FROM UserChangeLogs;
如您所见,两个触发器均按预期顺序激活。
触发指令信息
如果使用SHOW TRIGGERS语句显示触发器,则不会看到在相同事件和动作时间内触发器的激活顺序。
SHOW TRIGGERS FROM classicmodels WHERE `table` = 'products';
要查找此信息,需要查询information_schema数据库的触发器表中的action_order列,如下所示:
SELECT trigger_name, action_order FROM information_schema.triggers WHERE trigger_schema = 'classicmodels' ORDER BY event_object_table , action_timing , event_manipulation;
在本教程中,您学习了如何为具有相同事件和动作时间的表创建多个触发器。