一、触发器概念

触发器(trigger):监视某种情况,并触发某种操作。

触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/before) 4.触发事件(insert/update/delete)

语法:

create trigger triggerName

after/before insert/update/delete on 表名

for each row   #这句话在mysql是固定的

begin

sql语句;

end;

   同时使用Navicat for MySQL创建触发器方法如下图所示,但是建议使用语句操作。

        首先在Navicat for MySQL找到需要建立触发器对应的表,右键“设计表”,然后创建触发器。

二、简单的Insert触发器

假设存在一张学生表(student),包括学生的基本信息,学号(stuid)为主键。

另外存在一张成绩表(cj),对应每个学生包括一个值。其中number表示序号为主键,自动递增序列。它在插入过程中默认自增。同时假设成绩表中包括学生姓名和学号。

该成绩表目前没有值,先需要设计一个触发器,当增加新的学生时,需要在成绩表中插入对应的学生信息,至于具体math、chinese、english后面由老师打分更新即可。
        那么,如何设计触发器呢?
        1.首先它是一个插入Insert触发器,是建立在表student上的;
        2.然后是after,插入后的事件;
        3.事件内容是插入成绩表,主需要插入学生的学号和姓名,number为自增,而成绩目前不需要。
        注意:new表示student中新插入的值。

  1. create trigger ins_stu
  2. after insert on student for each row
  3. begin
  4. insert into cj ( stu_id, stu_name)
  5. values( new.stuid, new.username);
  6. end;

创建的触发器如下图所示:

  

然后插入数据:
        insert student values ('eastmount','111111','6','1991-12-05');
        同时插入两个数据,触发器正确执行了~

注意:创建触发器和表一样,建议增加判断:DROP TRIGGER IF EXISTS `ins_stu`;

三、判断值后调用触发器

这里简单讲述几个判断插入类型的触发器。
        比如触发器调用,当插入时间小时为20时,对数据进行插入:

  1. DROP TRIGGER IF EXISTS `ins_info`;
  2. create trigger ins_info
  3. after insert on nhfxelect for each row
  4. begin
  5. if HOUR(new.RecordTime)='20' then
  6. insert into nhfxbyhour (UnitDepName, UnitDepCode, ElectCost, TimeJG, RecordTime)
  7. values( '数统学院', '1', new.USERKWH, '20', new.RecordTime);
  8. end if;
  9. end;

这个触发器中,RecordTime为datetime类型,如"2016-08-28 20:10:00",这时hour()这个值为20才能插入;否则数据不能插入。同时可以date_format(new.RecordTime, '%Y-%m-%d')判断日期为某天或某年某月进行插入。
        同时,再如更新触发器,如果设置的值为某个范围,才进行操作或性别为"男"或"女"才进行操作。
        基本语法:
        if 判断条件 then
           sql语句;
        end if;

四、Update触发器-实时更新

假设存在一个实时插入数据的服务器,例如学生的消费金额或用电量等。
        StuCost:学生的用电数据,实时插入,Cost为每30秒消费金额,RecordTime为每分钟插入时间,datetime类型;
        StuCostbyHour:统计学生一小时的消费金额,HourCost为金额总数,按小时统计,TimeJD时间段,1~24,对应每小时,RecordTime为统计时间。
        现在需要设计一个实时更新触发器,当插入消费数据时,按小时统计学生的消费金额,同理,用电量等。

  1. DROP TRIGGER IF EXISTS `upd_info`;
  2. create trigger upd_info
  3. after insert on StuCost for each row
  4. begin
  5. update StuCostbyHour set HourCost = HourCost + new.Cost
  6. where (TimeJD = hour(new.RecordTime) + 1) and date_format(new.RecordTime, '%Y-%m-%d') = date_format(RecordTime, '%Y-%m-%d');
  7. end;

SQL语句中,需要获取插入的时间,然后通过TimeJD时间段和日期RecordTime找到对应的值,然后进行累加即可。如下图所示:

  

上图左边是实时插入数据,右边是触发器更新加和。后面会介绍MySQL实时事件:
        http://blog.csdn.net/zlp5201/article/details/38309095

五、触发器尽量避免

下面简单参考知乎和CSDN论坛,简单讲解几个内容:
问题一:
         大型系统必须得要存储过程和触发器吗? - 知乎
回答1:        
        我们先要弄清楚二个问题:
        1.什么是大型系统?
        2.你讨论的是什么领域的应用,可以大致分为二种:互联网、企业内部
        接下来给你举一些例子:
        1.SAP、peopleSoft、ERP等企业级别应用
        一般情况下,会使用存储过程和触发器,减少开发成本,毕竟其业务逻辑修改频繁,而且为通用,很多时候会把一些业务逻辑编写成存储过程,像Oracle会写成包,比存储过程更强大。
        另外一个原因是服务器的负载是可控,也即系统的访问人数首先是可控的,没有那么大,而且这些数据又非常关键,为此往往使用的设备也比较好,多用存储柜子支撑数据库。
        2.另外一类互联网行业的
        比如淘宝、知呼、微博等,数据库的压力是非常大的,也往往会最容易成为瓶颈,而且多用PC服务器支撑,用户量的增速是不可控的,同时在线访问的用户量也是不可控的,为此肯定会把业务逻辑放到其他语言的代码层,而且可以借助一些LVS等类型软硬件做负载均衡,以及平滑增减Web层的服务器,从而达到线性的增减而支持大规模的访问。
        所以不管你的这个系统是否庞大,首先要分业务支持的对象,系统最可能容易出现瓶颈的地方在那?
        当然也不是说互联网行业的应用就绝对不用存储过程,这个也不对,曾在阿里做的Oracle迁移MySQL系统确实用了,因为历史的原因,另外还有一些新系统也有用,比如晚上进行定期的数据统计的一些操作,不过有量上的控制。存储过程是好东西,要分场景,分业务类型来用就可以把握好。

回答2:
        肯定不能一刀切的说能用或者不能用,不同类型的系统、不同的规模、不同的历史原因都会有不同的解决方案。
        一般情况下,Web应用的瓶颈常在DB上,所以会尽可能的减少DB做的事情,把耗时的服务做成Scale Out,这种情况下,肯定不会使用存储过程;而如果只是一般的应用,DB没有性能上的问题,在适当的场景下,也可以使用存储过程。
        至于触发器,我是知道有这东西但从来没用过。我希望风险可控,遇到问题能够快速的找到原因,尽可能不会去使用触发器。

回答3:
        1.PLSQL可以大大降低parse/exec 百分比;
        2.存储过程可以自动完成静态SQL variable bind;
        3.存储过程大大减少了JDBC网络传输与交互,速度快;
        4.oracle 中存储过程内部commit为异步写,一定程度上减少了等redo日志落地时间;
        5.存储过程最大问题就是给数据库开发工作压力太大,另外架构升级时候会比较难解耦;
        6.触发器不推荐使用,触发操作能在业务层解决就在业务层解决,否则很难维护,而且容易产生死锁。

问题2:
        为什么大家都不推荐使用MySQL触发器而用存储过程?- segmentfault
回答1:
        1.存储过程和触发器二者是有很大的联系的,我的一般理解就是触发器是一个隐藏的存储过程,因为它不需要参数,不需要显示调用,往往在你不知情的情况下已经做了很多操作。从这个角度来说,由于是隐藏的,无形中增加了系统的复杂性,非DBA人员理解起来数据库就会有困难,因为它不执行根本感觉不到它的存在。
        2.再有,涉及到复杂的逻辑的时候,触发器的嵌套是避免不了的,如果再涉及几个存储过程,再加上事务等等,很容易出现死锁现象,再调试的时候也会经常性的从一个触发器转到另外一个,级联关系的不断追溯,很容易使人头大。其实,从性能上,触发器并没有提升多少性能,只是从代码上来说,可能在coding的时候很容易实现业务,所以我的观点是:摒弃触发器!触发器的功能基本都可以用存储过程来实现。
        3.在编码中存储过程显示调用很容易阅读代码,触发器隐式调用容易被忽略。
        4.存储过程的致命伤在于移植性,存储过程不能跨库移植,比如事先是在mysql数据库的存储过程,考虑性能要移植到oracle上面那么所有的存储过程都需要被重写一遍。

回答2:
        这种东西只有在并发不高的项目,管理系统中用。如果是面向用户的高并发应用,都不要使用。
        触发器和存储过程本身难以开发和维护,不能高效移植。触发器完全可以用事务替代。存储过程可以用后端脚本替代。

回答3:
        我觉得来自两方面的因素:
        1.存储过程需要显式调用,意思是阅读源码的时候你能知道存储过程的存在,而触发器必须在数据库端才能看到,容易被忽略。
        2.Mysql的触发器本身不是很好,比如after delete无法链式反应的问题。
        我认为性能上其实还是触发器占优势的,但是基于以上原因不受青睐。

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

项目运用:

//sr_main_da的触发器
//增加操作
create trigger zjgxk_insert_sr_main_da_trigger
after insert on sr_main_da for each row
BEGIN
insert into shjz_zjgxk(fk_sr_main_da,qhmc,xzqh,mhz,mhzsfz,mdjlx,mxsrs,mzjzje,mjzksrq,sys_xzqh,sys_scbj,sjbfyzj) values(new.pk_sr_main,new.qhmc,new.xzqh,new.mhz,new.mhzsfz,new.mdjlx,new.mxsrs,new.mzjzje,new.mjzksrq,new.sys_xzqh,new.sys_scbj,new.sjbfyzj,sjbfnf,sjbfyf);
END

//更新操作
create trigger zjgxk_update_sr_main_da_trigger
after update on sr_main_da for each row
BEGIN
delete from shjz_zjgxk where pk_sr_main = old.pk_sr_main;
insert into shjz_zjgxk(fk_sr_main_da,qhmc,xzqh,mhz,mhzsfz,mdjlx,mxsrs,mzjzje,mjzksrq,sys_xzqh,sys_scbj,sjbfyzj) values(new.pk_sr_main,new.qhmc,new.xzqh,new.mhz,new.mhzsfz,new.mdjlx,new.mxsrs,new.mzjzje,new.mjzksrq,new.sys_xzqh,new.sys_scbj,new.sjbfyzj,sjbfnf,sjbfyf);
END

//删除操作
create trigger zjgxk_delete_sr_main_da_trigger
after delete on sr_main_da for each row
BEGIN
delete from shjz_zjgxk where fk_sr_main_da = old.pk_sr_main;
END

有一点必须知道:写完触发器必须测试,很有可能因为触发器字段不对应导致往根表中插入数据时无法插入,报列数不匹配的错误,其根源不在于外界sql,而是触发器这边字段不对应

MySQL 触发器trigger的更多相关文章

  1. mysql触发器trigger 实例详解

    mysql触发器trigger 实例详解 (转自 https://www.cnblogs.com/phpper/p/7587031.html)   MySQL好像从5.0.2版本就开始支持触发器的功能 ...

  2. 如何使用MySQL触发器trigger

    阅读目录:触发器trigger的使用 创建触发器 单一执行语句.多执行语句 new.old详解 查看触发器 删除触发器:慎用触发器,不用就删除 Q:什么是触发器? A: 触发器是与表有关的数据库对象, ...

  3. mysql 触发器(trigger)

    触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...

  4. mysql 触发器 trigger用法 two (稍微复杂的)

    触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...

  5. MySQL触发器Trigger实例篇

    定义: 何为MySQL触发器? 在MySQL Server里面也就是对某一个表的一定的操作,触发某种条件(Insert,Update,Delete 等),从而自动执行的一段程序.从这种意义上讲触发器是 ...

  6. MySQL触发器 trigger学习

    触发器:一类特殊的事物.可监视某种数据操作,并触发相关操作(insert/update/delete).表中的某些数据改变,希望同一时候能够引起其他相关数据改变的需求. 作用:变化自己主动完毕某些语句 ...

  7. MySQL触发器 trigger之for each row

    for each row 每行受影响,触发器都运行.叫行级触发器. oracle 触发器中分行级触发器和语句级触发器,可不写for each row,不管影响多少行都仅仅运行一次. mysql不支持语 ...

  8. (转)MySQL触发器trigger示例详解

    一.什么是触发器 触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合.触发器的这种特性可以协助应用在数据库端确保数据的完整性. 举个例子,比如你现在有两个表[用户表]和[ ...

  9. mysql 触发器 trigger用法 three (稍微复杂的)

    MySQL包含对触发器的支持.触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行. 创建触发器 在MySQL中,创建触发器语法如下 ...

随机推荐

  1. java如何在静态方法中访问类的实例成员

    类的静态方法是不能直接访问实例的成员的,它只能访问同类的静态成员.访问实例的成员的话,可以参考一下这个方法,那就是把静态方法的参数设置为类的实例,这样通过参数传递的方式就可以访问实例的成员了,例子如下 ...

  2. Spark学习之路 (七)Spark 运行流程[转]

    Spark中的基本概念 (1)Application:表示你的应用程序 (2)Driver:表示main()函数,创建SparkContext.由SparkContext负责与ClusterManag ...

  3. Python机器学习及实践 课后小题

    目录 第二章 2.3章末小结 @(Python机器学习及实践-----从零开始通往Kaggle竞赛之路) 第二章 2.3章末小结 1 机器学习模型按照使用的数据类型,可分为监督学习和无监督学习两大类. ...

  4. 优先队列-UVA10603

    #include<cstdio> #include<cstring> #include<queue> using namespace std; typedef st ...

  5. PAT (Advanced Level) Practice 1028 List Sorting (25 分) (自定义排序)

    Excel can sort records according to any column. Now you are supposed to imitate this function. Input ...

  6. cartographer保存地图

    手持激光,并用cartographer建图,保存的地图是.pbstream格式 ht@ht:~$ rosservice call /write_state /home/ht/Desktop/carto ...

  7. 中文 json_encode之后字符长度问题

    问题描述: 将某个字符串$str 进行json编码,即json_encode($str)后变成Unicode字符存入数据库,会发现中文的长度明明没有超过设置的字符长度最大值,但是却抛出字段长度过长错误 ...

  8. ubuntu 部署Django项目+uwsgi+Nginx

    1.部署框架 Nginx负责静态资源请求,并且把无法处理的请求转发至uwsgi处理 2.安装并配置Nginx 2.1安装 apt-get install nginx (如果安装失败请先升级apt-ge ...

  9. PHP 冷知识

    1,执行Linux命令 <?php $a =`ls -a /`; // execute linux command echo '<pre>'.$a; 2.为变量起别名 <?ph ...

  10. Windows10通过命令行导出笔记本电池使用信息

    powercfg /batteryreport /output "D:\Thinkpad x1c\battery_report_2020_2_25.html" 可以导出电池的电池类 ...