3. 实现复杂的数据完整性规则
实现非标准的数据完整性检查和约束。触发器可产生比规则更为复杂的限制。与规则不同,触发器可以引用列或数据库对象。例如,触发器可回退任何企图吃进超过自己保证金的期货。
提供可变的缺省值。
4. 实现复杂的非标准的数据库相关完整性规则。触发器可以对数据库中相关的表进行连环更新。
例如,在auths表author_code列上的删除触发器可导致相应删除在其它表中的与之匹配的行。
在修改或删除时级联修改或删除其它表中的与之匹配的行。
在修改或删除时把其它表中的与之匹配的行设成NULL值。
在修改或删除时把其它表中的与之匹配的行级联设成缺省值。
触发器能够拒绝或回退那些破坏相关完整性的变化,取消试图进行数据更新的事务。当插入一个与其主健不匹配的外部键时,这种触发器会起作用。例如,可以在books.author_code 列上生成一个插入触发器,如果新值与auths.author_code列中的某值不匹配时,插入被回退。
5. 同步实时地复制表中的数据。
6. 自动计算数据值,如果数据的值达到了一定的要求,则进行特定的处理。例如,如果公司的帐号上的资金低于5万元则立即给财务人员发送警告数据。
二、触发器语法
==========
1. 创建语法四要素
监视地点(table)
监视事件(insert | update | delete)
触发时间(after | before)
触发事件(insert | update | delete)
2. 语法公式
CREATE TRIGGER
BEFORE|AFTER
INSERT|UPDATE|DELETE ON
FOR EACH ROW # 这句话在mysql是固定的
BEGIN
<触发的SQL语句>(调用NEW/OLD参数);
END
3. 语法参数说明
CREATE TRIGGER
{ BEFORE | AFTER } — 触发器触发时间设置:可以设置为事件发生前或后(前:一般用于校验;后:一般用于关联)。
{ INSERT | UPDATE | DELETE } – 设定触发事件:如执行insert、update或delete的过程时激活触发器。
ON
FOR EACH ROW — 触发器的执行间隔(必有的公式内容):FOR EACH ROW子句通知触发器 每隔一行执行一次动作,而不是对整个表执行一次。
<触发的SQL语句> — 触发器包含所要触发的SQL语句:这里的语句可以是任何合法的语句, 包括复合语句,但是这里的语句受的限制和函数的一样。当然,触发SQL中可以调用“触发了( INSERT | UPDATE | DELETE )触发器的那一行数据”。
例如下方代码:
create trigger add_stu
after insert on student for each row
begin
insert into student_score ( stu_id, score, rank)
values( NEW.stuid, NEW.username); – NEW用来表示将要(BEFORE)或已经(AFTER)插入的新数据
end;
4. NEW 与 OLD关键字详解
MySQL 中定义了 NEW 和 OLD,用来表示触发器的所在
【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
表中,触发了触发器的那一行数据,来引用触发器中发生变化的记录内容,具体地:
① 在INSERT型触发器中,NEW用来表示将要(BEFORE)或已经(AFTER)插入的新数据;
② 在UPDATE型触发器中,OLD用来表示将要或已经被修改的原数据,NEW用来表示将要或已经修改为的新数据;
③ 在DELETE型触发器中,OLD用来表示将要或已经被删除的原数据;
另外,原则上请编写简单高效的触发执行语句,以免悄无声息的浪费过多资源你还不知道!
三、实际应用
======
1. 数据准备
想我初三时常年倒数,成绩稳定,因此我拿当时几位老友排名数据来纪念一波(手动挠头)。给大家提供一个测试数据;
(沿用的前两篇“视图”、“存储过程”博文中的数据)
a.学生表
CREATE TABLE student
(
ID
int NOT NULL AUTO_INCREMENT ,
NAME
varchar(30) NOT NULL ,
SEX
char(2) NOT NULL ,
AGE
int NOT NULL ,
CLASS
varchar(10) NOT NULL ,
GRADE
varchar(20) NOT NULL ,
HOBBY
varchar(100) NULL ,
PRIMARY KEY (ID
)
)
#插入数据:
INSERT INTO student
(ID
, NAME
, SEX
, AGE
, CLASS
, GRADE
, HOBBY
) VALUES (‘1’, ‘陈哈哈’, ‘男’, ‘15’, ‘18班’, ‘9年级’, ‘上网’);
INSERT INTO student
(ID
, NAME
, SEX
, AGE
, CLASS
, GRADE
, HOBBY
) VALUES (‘2’, ‘扈亚鹏’, ‘男’, ‘15’, ‘18班’, ‘9年级’, ‘美食’);
INSERT INTO student
(ID
, NAME
, SEX
, AGE
, CLASS
, GRADE
, HOBBY
) VALUES (‘3’, ‘刘晓莉’, ‘女’, ‘14’, ‘18班’, ‘9年级’, ‘金希澈’);
INSERT INTO student
(ID
, NAME
, SEX
, AGE
, CLASS
, GRADE
, HOBBY
) VALUES (‘4’, ‘朱志鹏’, ‘男’, ‘15’, ‘18班’, ‘9年级’, ‘睡觉’);
INSERT INTO student
(ID
, NAME
, SEX
, AGE
, CLASS
, GRADE
, HOBBY
) VALUES (‘5’, ‘徐立楠’, ‘女’, ‘14’, ‘18班’, ‘9年级’, ‘阅读’);
INSERT INTO student
(ID
, NAME
, SEX
, AGE
, CLASS
, GRADE
, HOBBY
) VALUES (‘6’, ‘顾昊’, ‘男’, ‘15’, ‘5班’, ‘9年级’, ‘篮球’);
INSERT INTO student
(ID
, NAME
, SEX
, AGE
, CLASS
, GRADE
, HOBBY
) VALUES (‘7’, ‘陈子凝’, ‘女’, ‘15’, ‘18班’, ‘9年级’, ‘看电影’);
#插入结果:
b.成绩表
CREATE TABLE student_score
(
SID
int(11) NOT NULL,
S_NAME
varchar(30) NOT NULL,
TOTAL_SCORE
int(11) NOT NULL,
RANK
int(11) NOT NULL,
PRIMARY KEY (SID
)
)
#插入数据:
INSERT INTO student_score
(SID
, S_NAME
, TOTAL_SCORE
, RANK
) VALUES (‘1’, ‘陈哈哈’, ‘405’, ‘1760’);
INSERT INTO student_score
(SID
, S_NAME
, TOTAL_SCORE
, RANK
) VALUES (‘2’, ‘扈亚鹏’, ‘497’, ‘1000’);
INSERT INTO student_score
(SID
, S_NAME
, TOTAL_SCORE
, RANK
) VALUES (‘3’, ‘刘晓莉’, ‘488’, ‘1170’);
INSERT INTO student_score
(SID
, S_NAME
, TOTAL_SCORE
, RANK
) VALUES (‘4’, ‘朱志鹏’, ‘405’, ‘1770’);
INSERT INTO student_score
(SID
, S_NAME
, TOTAL_SCORE
, RANK
) VALUES (‘5’, ‘徐立楠’, ‘530’, ‘701’);
INSERT INTO student_score
(SID
, S_NAME
, TOTAL_SCORE
, RANK
) VALUES (‘6’, ‘顾昊’, ‘485’, ‘1286’);
INSERT INTO student_score
(SID
, S_NAME
, TOTAL_SCORE
, RANK
) VALUES (‘7’, ‘陈子凝’, ‘704’, ‘9’);
#插入结果:
c.逃课上网表
CREATE TABLE student_go_wangba
(
SID
int(9) NOT NULL,
SGW_NAME
varchar(30) DEFAULT NULL,
TIMES
int(9) DEFAULT NULL,
PRIMARY KEY (SID
)
)
#插入数据:
INSERT INTO student_go_wangba
(SID
, SGW_NAME
, TIMES
) VALUES (‘1’, ‘陈哈哈’, 15);
INSERT INTO student_go_wangba
(SID
, SGW_NAME
, TIMES
) VALUES (‘2’, ‘扈亚鹏’, 1);
INSERT INTO student_go_wangba
(SID
, SGW_NAME
, TIMES
) VALUES (‘3’, ‘刘晓莉’, 0);
INSERT INTO student_go_wangba
(SID
, SGW_NAME
, TIMES
) VALUES (‘4’, ‘朱志鹏’, 63);
INSERT INTO student_go_wangba
(SID
, SGW_NAME
, TIMES
) VALUES (‘5’, ‘徐立楠’, 0);
INSERT INTO student_go_wangba
(SID
, SGW_NAME
, TIMES
) VALUES (‘6’, ‘顾昊’, 7);
INSERT INTO student_go_wangba
(SID
, SGW_NAME
, TIMES
) VALUES (‘7’, ‘陈子凝’, 0);
#插入结果:
2. 使用案例
表数据:以上面的三张表为例;学生表(student)、学生成绩表(student_score)、逃课上网次数表(student_go_wangba),均已学号(stuid)为主键。
需求:
需要设计一个触发器A,当增加新的学生时,需要在成绩表(student_score)中插入对应的学生信息,至于“分值、排名”字段为0即可;后面由老师打分更新。
需要设计一个触发器B,当增加新的学生成绩信息时,需要在逃课上网表(student_go_wangba)中插入对应的学生信息,至于“逃课上网次数”字段为0即可;后面由教导主任“小平头”去更新。(该触发器意义在于:测试after insert链式反应是否支持)
那么,如何设计触发器A呢?
首先它是一个插入Insert触发器,是建立在表student上的;
然后是after,插入后的事件;
事件内容是插入成绩表,需要插入学生的学号和姓名,number为自增,而“分值、排名”目前不需要。
触发器A:
– 新增触发器A,当student表插入数据时,student_score表生成初始关联数据
DROP TRIGGER IF EXISTS add_stu;
create trigger add_stu
after insert on student for each row
begin
INSERT INTO student_score (SID, S_NAME, TOTAL_SCORE, RANK)
VALUES (new.ID,new.NAME, 0, 0 );
end;
触发器B:
– 新增触发器B,当student_score表插入数据时,student_go_wangba表生成初始关联数据
DROP TRIGGER IF EXISTS add_score;
create trigger add_score
after insert on student_score for each row
begin
INSERT INTO student_go_wangba (SID, SGW_NAME, TIMES)
VALUES (new.SID,new.S_NAME, 0 );
end;
查询一下我的触发器:
show triggers \G
– "\G"是干什么用的?
– 作用:在shell中树形展示
如果在Navicat中就不用 \G,直接"show triggers;"就可以。
show triggers;
执行触发器,向student表中加入一条数据:
INSERT INTO student
(ID
, NAME
, SEX
, AGE
, CLASS
, GRADE
, HOBBY
)
VALUES (‘8’, ‘李昂’, ‘男’, ‘15’, ‘18班’, ‘9年级’, ‘看片儿’);
结果如下图所示:
同时插入三个数据,两个触发器正确执行了~
注意:创建触发器和表一样,建议增加判断:DROP TRIGGER IF EXISTS `add_stu`;
表数据:以上面的三张表为例;学生表(student)、学生成绩表(student_score)、逃课上网次数表(student_go_wangba),均已学号(stuid)为主键。
需求:有些老是逃课上网的学生被开除,需要删掉所有信息,以免给学校抹黑~~~
需要设计一个触发器C,当删除新的学生时,需要在成绩表(student_score)中删除对应的学生信息。
需要设计一个触发器D,当删除新的学生成绩信息时,需要在逃课上网表(student_go_wangba)中删除对应的学生信息。(该触发器意义在于:测试after delete链式反应是否支持)
那么,如何设计触发器C呢?
首先它是一个插入delete触发器,是建立在表student上的;
然后是after,插入后的事件;
事件内容是关联删除成绩表数据,需要删除学生的学号即可。
触发器C:
– 新增触发器C,当student表删除数据时,student_score表删除关联数据
DROP TRIGGER IF EXISTS del_stu;
create trigger del_stu
after delete on student for each row
begin
DELETE FROM student_score where SID = old.ID;
end;
触发器D:
– 新增触发器D,当student_score表删除数据时,student_go_wangba表删除关联数据
DROP TRIGGER IF EXISTS del_score;
create trigger del_score
after delete on student_score for each row
begin
DELETE FROM student_go_wangba where SID = old.SID;
end;
执行触发器,从student表中删除一条数据:
DELETE FROM student
where NAME = ‘朱志鹏’
结果如下图所示:
同时删除三个数据,触发器正确执行了。朱志鹏同学数据已经木得了~
注意:创建触发器和表一样,建议增加判断:DROP TRIGGER IF EXISTS `del_stu`;
跟Insert触发器、Delete触发器同理,这里不再赘述
四、触发器有哪些缺陷 @江湖中人
================
下面通过参考知乎、CSDN论坛、天涯社区,简单讲解几个内容供大家参考:
问题一: 触发器有哪些限制和注意事项