12.1、触发器介绍
触发器是一种特殊的存储过程,只要满足一定条件,对数据表进行INSERT、UPDATE、DELETE操作时,数据库系统就会自动执行触发器中定义的程序语句,以进行维护数据完整性或其他一些特殊的任务。
触发器是MYSQL的数据库对象之一,与存储过程非常相似,都需要声明﹑执行等。但是触发器的执行不是由程序调用的,也不是手工启动的,而是由事件来触发的。
MySQL提供了两个逻辑表NEW和OLD,NEW和OLD的表结构与触发器所在数据表的结构完全一致,当触发器的执行完成之后,这两个表也会被自动删除。
OLD表用来存放更新前的记录:
对于UPDATE语句,OLD表中存放的是更新前的记录(更新完后即被删除);
对于DELETE语句,该表中存放的是被删除的记录。
NEW表用来存放更新后的记录:
对于INSERT语句,NEW表中存放的是要插入的记录;
对于UPDATE语句,该表中存放的是要更新的记录。
12.2、测试的表结构
CREATE TABLE `student` (
`sno` varchar(20) NOT NULL,
`sname` varchar(20) DEFAULT NULL,
`ssex` enum('男','女','') DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`sdept` varchar(20) DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
PRIMARY KEY (`sno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `score` (
`sno` varchar(20) DEFAULT NULL,
`courseid` int(11) DEFAULT NULL,
`grade` tinyint(4) DEFAULT NULL,
KEY `fk_courseid` (`courseid`),
KEY `fk_snoid` (`sno`),
CONSTRAINT `fk_courseid` FOREIGN KEY (`courseid`) REFERENCES `course` (`courseid`),
CONSTRAINT `fk_snoid` FOREIGN KEY (`sno`) REFERENCES `student` (`sno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
12.3、触发器管理
12.3.1、创建触发器
12.3.1.0、注意事项
请注意:
若有外键约束,这个更新语句执行不成功。
可以通过以下语句让外键约束暂时失效:SET FOREIGN_KEY_CHECKS=0;
12.3.1.1、update触发器
-- 1、update,创建触发器,当sno更新时,则更新score表
-- after:更新之后执行,before:更新之前执行
delimiter $$
create trigger sno_update after update on student for each row
begin
update score set sno=new.sno where sno=old.sno;
end$$
delimiter ;
-- 更新时,查看触发器,是否生效
update student set sno='99999' where sname='洛燕妮';
12.3.1.2、insert触发器
-- 2、delete,创建触发器,当学生被旧除时,同步删除score表该学生数据
delimiter $$
create trigger sno_delete after delete on student for each row
begin
delete from score where sno=old.sno;
end$$
delimiter ;
-- 测试触发器是否生效
delete from student where sno='99999';
12.3.1.3、delete触发器
-- 3、insert,创建触发器,插入数据时,sno自动+1
delimiter $$
create trigger trig_auto before insert on student for each row
begin
declare index_sno int;
select max(sno) into index_sno from student;
set new.sno=index_sno+1;
end$$
delimiter ;
-- 插入数据,检查是否有更新
insert into student values ('123','ok','男',88,'计算机系','2000-01-03 13:12:12');
12.3.2、查看触发器
12.3.3、删除触发器
12.4、实战
12.4.1、实战1【阻止更新某列的数据】
delimiter $$
create trigger sno_update before update on student for each row
begin
set new.sno=old.sno;
end$$
delimiter ;
12.4.2、实战2【阻止插入数据】
delimiter $$
create trigger check_student before insert on student for each row
begin
declare vcount int;
select count(ssex) into vcount from student where ssex='男';
if vcount>=8 then
signal sqlstate '45000' set message_text='不允许插入';
end if;
end$$
delimiter ;