MySQL触发器
Posted hopeless-dream
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL触发器相关的知识,希望对你有一定的参考价值。
介绍
触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。 触发器的特性: 1、有begin end体,begin end;之间的语句可以写的简单或者复杂 2、什么条件会触发:I、D、U 3、什么时候触发:在增删改前或者后(before/after) 4、触发频率:针对每一行执行 5、触发器定义在表上,附着在表上。 也就是由事件来触发某个操作,事件包括INSERT语句,UPDATE语句和DELETE语句;可以协助应用在数据库端确保数据的完整性。
语法
CREATE TRIGGER trigger_name trigger_time: { BEFORE | AFTER } ON tbl_name FOR EACH ROW trigger_body trigger_event: { INSERT | UPDATE | DELETE }
变量类型
类型 | NEW和OLD使用 |
INSERT | NEW变量,获取Insert后的数据。 |
update | NEW变量,获取update后的数据;OLD变量,获取update前的数据。 |
delete | OLD变量,获取删除前数据 |
创建insert触发器
建表
CREATE TABLE t4_log( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, act_user VARCHAR(64), act_type VARCHAR(50) , act_time VARCHAR(50), act_id VARCHAR(20), act_comment VARCHAR(100));
创建触发器
当t4表有新数据插入的时候,t4_log表会记录操作信息。
DELIMITER $$ CREATE /*[DEFINER = { user | CURRENT_USER }]*/ TRIGGER `world`.`t_t4` AFTER INSERT ON `world`.`t4` FOR EACH ROW BEGIN INSERT INTO t4_log(act_user,act_type,act_time,act_id,act_comment) VALUES (USER(),\'insert\',NOW(),new.id, CONCAT(\'insert into t4 values(\',new.id,\',\',new.name,\',\',new.age,\',\',new.gender,\');\')); END$$ DELIMITER ;
查看触发器
mysql> show triggers; +---------+--------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+------------------------+----------+---------------+----------------------+----------------------+--------------------+ | Trigger | Event | Table | Statement | Timing | Created | sql_mode | Definer | character_set_client | collation_connection | Database Collation | +---------+--------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+------------------------+----------+---------------+----------------------+----------------------+--------------------+ | t_t4 | INSERT | t4 | BEGIN insert into t4_log(act_user,act_type,act_time,act_id,act_comment) values (user(),\'insert\',now(),new.id, concat(\'insert into t4 values(\',new.id,\',\',new.name,\',\',new.age,\',\',new.gender,\');\')); END | AFTER | 2020-06-15 04:08:49.51 | | root@10.0.0.% | utf8 | utf8_general_ci | utf8mb4_0900_ai_ci | +---------+--------+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+------------------------+----------+---------------+----------------------+----------------------+--------------------+ 1 row in set (0.00 sec)
插入数据
存储过程如下:
DELIMITER $$ USE `world`$$ DROP PROCEDURE IF EXISTS `p_iterate`$$ CREATE DEFINER=`root`@`10.0.0.%` PROCEDURE `p_iterate`( IN num INT) BEGIN DECLARE u_n VARCHAR(64); DECLARE u_a TINYINT; DECLARE u_g CHAR(1); DECLARE i INT DEFAULT 1; lab1: WHILE i < num DO SELECT SUBSTR(REPLACE(UUID(),\'-\',\'\'),1,6) INTO u_n; SELECT CEIL(RAND()*18)+17 INTO u_a; SELECT SUBSTR(\'MF\',CEIL(RAND()*2),1) INTO u_g; SET i = i+1; IF MOD(i,2)=0 THEN ITERATE lab1; ELSE INSERT INTO t4(NAME,age,gender) VALUES(CONCAT(u_n,\'_\',i),u_a,u_g); END IF; END WHILE lab1; END$$ DELIMITER ;
调用
TRUNCATE TABLE t4; CALL p_iterate(100) SELECT * FROM t4; SELECT * FROM t4_log;
delete触发器
创建触发器
DELIMITER $$ USE `world`$$ DROP TRIGGER /*!50032 IF EXISTS */ `t_delete`$$ CREATE /*!50017 DEFINER = \'root\'@\'10.0.0.%\' */ TRIGGER `t_delete` BEFORE DELETE ON `t4` FOR EACH ROW BEGIN INSERT INTO t4_log(act_user,act_type,act_time,act_id,act_comment) VALUES(USER(),\'delete\',NOW(),old.id, CONCAT(\'delete from t4 where id=\',old.id,\';\')); END; $$ DELIMITER ;
调用
DELETE FROM t4 WHERE id=5; SELECT * FROM t4_log;
update触发器
修改表结构(添加一个记录反向操作的字段)
mysql> alter table t4_log add column act_rev varchar(64); Query OK, 0 rows affected (0.01 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> desc t4_log -> ; +-------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | act_user | varchar(64) | YES | | NULL | | | act_type | varchar(50) | YES | | NULL | | | act_time | varchar(50) | YES | | NULL | | | act_id | varchar(20) | YES | | NULL | | | act_comment | varchar(100) | YES | | NULL | | | act_rev | varchar(64) | YES | | NULL | | +-------------+--------------+------+-----+---------+----------------+ 7 rows in set (0.00 sec)
创建触发器
DELIMITER $$ USE `world`$$ DROP TRIGGER /*!50032 IF EXISTS */ `t_update`$$ CREATE /*!50017 DEFINER = \'root\'@\'10.0.0.%\' */ TRIGGER `t_update` AFTER UPDATE ON `t4` FOR EACH ROW BEGIN INSERT INTO t4_log(act_user,act_type,act_time,act_id,act_comment,act_rev) VALUES (USER(),\'update\',NOW(),old.id, CONCAT(\'update t4 set name=\\\'\',new.name,\'\\\',age=\',new.age,\',gender=\\\'\',new.gender,\'\\\' where id=\',new.id), CONCAT(\'update t4 set name=\\\'\',old.name,\'\\\',age=\',old.age,\',gender=\\\'\',old.gender,\'\\\' where id=\',old.id)); END; $$ DELIMITER ;
查一下更新前的值
mysql> select * from t4 where id=21; +----+-----------+-----+--------+ | id | name | age | gender | +----+-----------+-----+--------+ | 21 | 7ec897_43 | 30 | F | +----+-----------+-----+--------+ 1 row in set (0.00 sec)
更新表
mysql> update t4 set name=\'tom\',age=13,gender=\'F\' where id=21; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
查看表数据
mysql> select * from t4_log; +----+----------------+----------+---------------------+--------+--------------------------------------------------------+--------------------------------------------------------------+ | id | act_user | act_type | act_time | act_id | act_comment | act_rev | +----+----------------+----------+---------------------+--------+--------------------------------------------------------+--------------------------------------------------------------+ | 1 | root@localhost | update | 2020-06-15 11:31:03 | 21 | update t4 set name=\'tom\',age=13,gender=\'F\' where id=21 | update t4 set name=\'7ec897_43\',age=30,gender=\'F\' where id=21 | +----+----------------+----------+---------------------+--------+--------------------------------------------------------+--------------------------------------------------------------+ 1 row in set (0.00 sec)
验证逆向操作
mysql> update t4 set name=\'7ec897_43\',age=30,gender=\'F\' where id=21; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t4 where id=21; +----+-----------+-----+--------+ | id | name | age | gender | +----+-----------+-----+--------+ | 21 | 7ec897_43 | 30 | F | +----+-----------+-----+--------+ 1 row in set (0.00 sec)
应用中的示例:商品库存自动更新
商品信息表
create table goods( id int primary key auto_increment, name varchar(20) not null, price decimal(10,2) default 1, inv int comment \'库存数量\');
insert into goods values (null,\'华为\',11999,1000), (null,\'苹果\',15999,50), (null,\'惠普\',5999,2000), (null,\'小米\',10999,2500), (null,\'戴尔\',6999,3000);
订单表
create table orders( id int primary key auto_increment, o_id int not null comment \'商品id\', o_number int comment \'商品数量\' ) ;
创建触发器
create trigger after_order after insert on orders for each row begin update goods set inv = inv - new.o_number where id = new.id; end insert into orders(o_id,o_number) values(1,1,3);
以上是关于MySQL触发器的主要内容,如果未能解决你的问题,请参考以下文章