一、什么是触发器
触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性。
举个例子,比如你现在有两个表【用户表】和【日志表】,当一个用户被创建的时候,就需要在日志表中插入创建的log日志,如果在不使用触发器的情况下,你需要编写程序语言逻辑才能实现,但是如果你定义了一个触发器,触发器的作用就是当你在用户表中插入一条数据的之后帮你在日志表中插入一条日志信息。当然触发器并不是只能进行插入操作,还能执行修改,删除。
二、触发器的特性:
- 什么条件会触发:INSERT语句,UPDATE语句和DELETE语句
- 什么时候触发:在增删改前或者后
- 触发频率:针对每一行执行
- 触发器定义在表上,附着在表上。
三、创建触发器
创建触发器的语法如下:
CREATE TRIGGER
trigger_name
trigger_time trigger_event ON
table_name
FOR EACH ROW
trigger_body
trigger_name:触发器的名称
tirgger_time:触发执行的时间,为BEFORE或者AFTER,在事件之前或是之后
trigger_event:触发事件,为INSERT、DELETE或者UPDATE
- INSERT型触发器:插入某一行时激活触发器,可能通过INSERT、LOAD DATA、REPLACE 语句触发(load data语句是将文件的内容插入到表中,相当于是insert语句,而replace语句在一般的情况下和insert差不多,但是如果表中存在primary 或者unique索引的时候,如果插入的数据和原来的primary key或者unique相同的时候,会删除原来的数据,然后增加一条新的数据,所以有的时候执行一条replace语句相当于执行了一条delete和insert语句);
- UPDATE型触发器:更改某一行时激活触发器,可能通过UPDATE语句触发;
- DELETE型触发器:删除某一行时激活触发器,可能通过DELETE、REPLACE语句触发。
table_name:表示建立触发器的表名,就是在哪张表上建立触发器
FOR EACH ROW:表示任何一条记录上的操作满足触发事件都会触发该触发器,也就是说触发器的触发频率是针对每一行数据触发一次。
trigger_body:触发器的程序体,可以是一条SQL语句或者是用BEGIN和END包含的多条语句
1、创建只有一个执行语句的触发器
CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件 ON 表名 FOR EACH ROW 执行语句;
例如:
创建了一个名为trig1的触发器,一旦在work表中有插入动作,就会自动往time表里插入当前时间
CREATE TRIGGER trig1 AFTER INSERT ON work FOR EACH ROW INSERT INTO time VALUES(NOW());
2、创建有多个执行语句的触发器
CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件
ON 表名 FOR EACH ROW
BEGIN
执行语句列表
END;
其中,BEGIN与END之间的执行语句列表参数表示需要执行的多个语句,不同语句用分号隔开
tips:一般情况下,mysql默认是以 ; 作为结束执行语句,与触发器中需要的分行起冲突
为解决此问题可用DELIMITER,如:DELIMITER ||,可以将结束符号变成||
当触发器创建完成后,可以用DELIMITER ;来将结束符号变成;
例如:
定义一个触发器,一旦有满足条件的删除操作,就会执行BEGIN和END中的语句
DELIMITER ||
CREATE TRIGGER trig2 BEFORE DELETE
ON work FOR EACH ROW
BEGIN
NSERT INTO time VALUES(NOW());
INSERT INTO time VALUES(NOW());
END||
DELIMITER ;
3、NEW与OLD详解
MySQL 中定义了 NEW 和 OLD,用来表示触发器的所在表中,触发了触发器的那一行数据,来引用触发器中发生变化的记录内容,具体地:
- 在INSERT型触发器中,NEW用来表示将要(BEFORE)或已经(AFTER)插入的新数据;
- 在UPDATE型触发器中,OLD用来表示将要或已经被修改的原数据,NEW用来表示将要或已经修改为的新数据;
- 在DELETE型触发器中,OLD用来表示将要或已经被删除的原数据;
使用方法:
NEW.columnname:新增行的某列数据(columnName为相应数据表某一列名) OLD.columnname:删除行的某列数据(columnName为相应数据表某一列名)
另外,OLD是只读的,而NEW则可以在触发器中使用 SET 赋值,这样不会再次触发触发器,造成循环调用(如每插入一个学生前,都在其学号前加“2013”)。
delimiter $$
CREATE TRIGGER upd_check BEFORE UPDATE ON account
FOR EACH ROW
BEGIN
IF NEW.amount < 0 THEN
SET NEW.amount = 0;
ELSEIF NEW.amount > 100 THEN
SET NEW.amount = 100;
END IF;
END$$
delimiter ;
四、查看触发器
1、SHOW TRIGGERS语句查看触发器信息
#查询所有触发器
SHOW TRIGGERS
结果,显示所有触发器的基本信息;无法查询指定的触发器。
2、在information_schema.triggers表中查看指定触发器信息
#查询指定触发器
SELECT * FROM information_schema.triggers WHERE TRIGGER_NAME='trig1';
结果,显示所有触发器的详细信息;同时,该方法可以查询制定触发器的详细信息。
Tips:所有触发器信息都存储在information_schema数据库下的triggers表中,可以使用SELECT语句查询,如果触发器信息过多,最好通过TRIGGER_NAME字段指定查询。
五、删除触发器
DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name
#删除指定触发器
drop trigger trig1;
删除触发器之后最好使用上面的方法查看一遍;同时,也可以使用database.trig来指定某个数据库中的触发器。
Tips:如果不需要某个触发器时一定要将这个触发器删除,以免造成意外操作,这很关键。
总结
触发器是基于行触发的,所以删除、新增或者修改操作可能都会激活触发器,所以不要编写过于复杂的触发器,也不要增加过得的触发器,这样会对数据的插入、修改或者删除带来比较严重的影响,同时也会带来可移植性差的后果,所以在设计触发器的时候一定要有所考虑。
触发器是一种特殊的存储过程,它在插入,删除或修改特定表中的数据时触发执行,它比数据库本身标准的功能有更精细和更复杂的数据控制能力。