作者:天山老妖S

链接:http://blog.51cto.com/9291927

一、触发器简介

1、触发器简介

触发器是和表关联的特殊的存储过程,可以再插入,删除或修改表中的数据时触发执行,比数据库本身标准的功能有更精细和更复杂的数据控制能力。

2、触发器的优点

A、安全性

可以基于数据库的值使用户具有操作数据库的某种权利。可以基于时间限制用户的操作,例如不予许下班后和节假日修改数据库数据;可以基于数据库中的数据限制用户的操作,例如不允许股票的价格的升幅一次超过10%。

B、审计

可以跟踪用户对数据库的操作。审计用户操作数据库的语句;把用户对数据库的更新写入审计表。

C、实现复杂的数据完整性规则

实现非标准的数据完整性检查和约束。触发器可产生比规则更为复杂的限制。与规则不同,触发器可以引用列或数据库对象。例如,触发器可回退任何企图吃进超过自己保证金的期货。提供可变的缺省值。

D、实现复杂的非标准的数据库相关完整性规则。

触发器可以对数据库中相关的表进行连环更新。

在修改或删除时级联修改或删除其它表中的与之匹配的行。

在修改或删除时把其它表中的与之匹配的行设成NULL值。

在修改或删除时把其它表中的与之匹配的行级联设成缺省值。

触发器能够拒绝或回退那些破坏相关完整性的变化,取消试图进行数据更新的事务。

E、同步实时地复制表中的数据。

F、SQL触发器提供了运行计划任务的另一种方法。自动计算数据值,如果数据的值达到一定的要求,则进行特定的处理。例如,如果公司的账号上的资金低于5万元则立即给财务人员发送警告数据。

3、触发器的限制

A、触发程序不能调用将数据返回客户端的存储程序,也不能使用采用CALL语句的动态SQL语句,但是允许存储程序通过参数将数据返回触发程序,也就是存储过程或者函数通过OUT或者INOUT类型的参数将数据返回触发器是可以的,但是不能调用直接返回数据的过程。

B、不能在触发器中使用以显示或隐式方式开始或结束事务的语句,如 SELECT TRANS-ACTION,COMMIT或ROLLBACK。

二、触发器的使用

1、创建触发器

创建触发器的语法:

CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmt

trigger_name:触发器的名称。

trigger_time:触发时机,为BEFIRE或者AFTER。

trigger_event:触发事件,为INSERT、DELETE或者UPDATE。

tb_name:表示建立触发器的表名,在哪张表上建立触发器。

trigger_stmt:触发器的程序体,可以是一条SQL语句或者是用BEGIN和END包含的多条语句。

FOR EACH ROW 表示任何一条记录上的操作满足触发事件都会触发该触发器。

MySQL除了对INSERT、UPDATE、DELETE基本操作进行定义外,还定义了LOAD DATA和REPLACE语句,这两种语句也能引起上述6种类型的触发器的触发。

LOAD DATA 语句用于将一个文件装入到一个数据表中,想当于一系列的INSERT操作。

REPLACE语句一般来说和INSERT语句很像,只是在表中有primary key 或 unique 索引一致时,会先删除原来的数据,然后增加一条新数据。

INSERT型触发器:插入某一行时激活触发器,通过INSERT、LOAD DATA、REPLACE语句触发;

UPDATE型触发器:更改某一行时激活触发器,通过UPDATE语句触发;

DELETE型触发器:删除某一行时激活触发器,通过DELETE、REPLACE语句触发。

变量声明:

DECLARE var_name[,...] type [DEFAULT value]

对变量赋值采用SET语句,语法为:

SET var_name = expr [,var_name = expr] ...

MySQL中定义了NEW和OLD,用来表示触发器的所在表中,触发了触发器的哪一行数据。

在INSERT型触发器中,NEW用来表示将要(BEFORE)或已经(AFTER)插入的新数据;

在UPDATE型触发器中,OLD用来表示将要或已经被修改的原数据,NEW用来表示将要或已经修改为的新数据;

在DELETE型触发器中,OLD用来表示将要或已经被删除的原数据;

使用方法:NEW.columnName(columnName为相应数据表某一列名)

另外,OLD是只读的,而NEW则可以在触发器中使用SET赋值,不会再次触发触发器,造成循环调用。

2、删除触发器

DROP TRIGGER [IF EXISTS] [schema_name.] trigger_name

schema_name是数据库的名称,是可选的。如果省略了schema,将从当前数据库中舍弃触发程序。trigger_name是要删除的触发器的名称。

3、触发器信息查看

在MySQL中,所有的触发器的定义都存在于INFORMATION_SCHEMA数据库的triggers表中,可以通过查询命令SELECT来查看,具体语法如下:

SHOW TRIGGERS [FROM schema_name];

触发器的执行顺序

InnoDB数据库,若SQL语句或触发器执行失败,MySQL会回滚事务,有:

A、如果BEFORE触发器执行失败,SQL无法正确执行。

B、SQL执行失败时,AFTER型触发器不会触发。

C、AFTER类型的触发器执行失败,SQL会回滚。

MySQL的触发器是按照BEFORE触发器、行操作、AFTER触发器的顺序执行的,其中任何一步发生错误都不会继续执行剩下的操作,如果对事务表进行的操作,如果出现错误,那么将会被回滚,数据可能会出错。

三、触发器应用

1、实现业务逻辑

客户下订单订购商品,商品表自动减少数量。

在商品表创建删除触发器,删除某商品,自动删除该商品的订单。创建产品表,有产品编号,产品名称、产品数量和产品价格四列,其中产品编号自增长列,并且设置成主键。

create table product
(
pid int PRIMARY KEY AUTO_INCREMENT,
pname VARCHAR(10),
price DOUBLE,
pnum INT)ENGINE=innoDB default CHARSET=utf8;

创建订单表,有三列,订单编号、产品编号和数量,其中订单编号自增长列,并设置成主键。

create table orders
(oid INT PRIMARY KEY AUTO_INCREMENT,
pid INT,
onum INT)ENGINE=innoDB DEFAULT CHARSET=utf8;

插入三种产品,产品名称和数量以及价格。

insert into product(pname,pnum,price) values('桃子',100,2);

insert into product(pname,pnum,price) values('苹果',80,8);

insert into product(pname,pnum,price) values('香蕉',50,5);

在订单表上创建触发器,当有订单,会根据订单的产品编号和数量自动减少产品的数量。触发器中NEW代表一个表,存放插入的订单记录。

create trigger trigger_order AFTER INSERT ON orders FOR EACH ROW BEGIN UPDATE product SET pnum = pname-NEW.onum where pid = NEW.pid; END

插入两个订单

INSERT INTO orders(pid,onum) VALUES(1,10); INSERT INTO orders(pid,onum) VALUES(2,5);

查看产品表,可以看到对应的产品数量减少。操作由订单表的Insert触发器完成。

在订单表上创建新的触发器,当订单定的某产品产品数量大于产品库存,禁止下订单,也就是禁止在订单表中插入记录。

一张表中只能有一个INSERT类型的触发器,先删除INSERT触发器。

drop trigger trigger_order;

MySQL不能在触发器中通过回滚事务取消操作,但如果触发器的SQL语句执行过程中出现错误,会自动撤销操作,曲线实现事务回滚。

create trigger trigger_order
BEFORE INSERT ON orders FOR EACH ROW
BEGINDECLARE var int;DECLARE mesg varchar(20);
SELECT pnum INTO var FROM product where pid=NEW.pid;IF var<NEW.onum
  THEN  SELECT XXXX INTO mesg;ELSE
  UPDATE product SET pnum=pnum-NEW.onum where pid=NEW.pid;
END IF;
END

插入订单,看看如果库存不够是否还能插入成功。

INSERT INTO orders(pid, onum) VALUES(1,110);

2、实现安全

A、限制插入记录的日期

在订单表上创建插入触发器,周六周日不允许下订单。

create trigger trigger_limitDateBEFORE INSERT ON orders FOR EACH ROWBEGINDECLARE mesg varchar(10);
IF DAYNAME(now())='sunday' or DAYNAME(now())='saturday'
  THEN SELECT XXXXX INTO mesg;
ELSE
  SET mesg='允许插入订单';END IF;END

验证上面创建的触发器是否工作正常,看看当前时间是否是周六周日,向订单表插入记录,检查是否能够成功。

insert into orders(pid,onum) values(3,30)

B、限制数据更改的范围

在产品表上创建更新触发器,限制产品价格一次上调不能超过20%。

触发器设置成before update,在更改前检查价格增长幅度是否超过20%,如果超过就产生错误,取消操作。

更新操作分为两步,第一步是删除原来的记录,第二部是插入新记录。原来的记录在old表中,新记录在new表中。触发器中new.price存放的是新价格,old.price是原来的价格。

create trigger trigger_limitIncreasePrice
BEFORE UPDATE ON product FOR EACH ROW
BEGIN
DECLARE mesg varchar(10);if (NEW.price-OLD.price)*100/OLD.price > 20
  then select XXXX into mesg;else
  set mesg='更改成功';
end if;
END

验证触发器

update product set price = 20 where pid = 1;

3、实现数据完整性

使用触发器可以限制表插入某列的数值范围。

创建一个学生表,有四列,姓名、性别、手机和邮箱。

create table personinfo
(
sname VARCHAR(5),
sex CHAR(1),
phone VARCHAR(11)
)ENGINE=innoDB default CHARSET=utf8;

A、指定性别列的取值范围

创建触发器,限制性别列,只允许输入“男”和“女”。

before insert触发器,不满足条件执行有错误SQL语句,退出。

create trigger trigger_limitSexbefore insert on personinfo for each rowbegindeclare mesg varchar(10);
if NEW.sex='男' or NEW.sex='女'
then   set mesg='更改成功';
else
  select xxxx into mesg;end if;End

验证触发器

insert into personinfo VALUES('孙悟空','女','18900000000'); insert into personinfo VALUES('唐僧','男','18900000001');

B、限制手机列的取值类型和长度

创建触发器,只允许phone列输入的手机号只能是11位数字,且第一位数字是1。

create trigger trigger_limitPhone
before insert on personinfo for each row
begin
declare mesg varchar(10);if NEW.phone regexp '[1][0-9]{10}'
  then set mesg='插入成功';else
  select xxxx into mesg;
end if;
End

验证触发器,如果手机列插入的值位数不对或者第一位不是1,插入都将失败。

insert into personinfo VALUES('唐僧','男','28900000001');

4、使用触发器审计

使用触发器实现对personinfo表数据操作的跟踪,将跟踪事件记录到一张审计表中review。

create table review
(
username VARCHAR(20),action VARCHAR(10),
studentID CHAR(5),
sname CHAR(10),
actionTime TIMESTAMP);

A、创建触发器记录插入操作

create trigger trigger_insertbefore insert on personinfo for each rowbegininsert into review values(user(),'insert',new.sname,now());End

插入personinfo表一条记录

insert into personinfo values('孙悟空','男','13008080808');

查看review表中增加的INSERT记录

select * from review

B、创建触发器记录删除操作

create trigger trigger_delete after delete on personinfo for each row begin insert into review values(user(),'delete',old.sname,now()); end

从personinfo删除一条记录

delete from personinfo where sname = '孙悟空';

查看reivew表中增加的DELETE记录

C、创建触发器记录修改操作

create trigger trigger_updateafter UPDATE on personinfo for each rowbegininsert review values(user(),'update',new.sname,now());End

更新personinfo表中名字为'孙悟空'的phone。

update personinfo set phone = '189080808' where sname = '孙悟空';

查看reivew表中增加的UPDATE记录

喜欢的小伙伴们可以搜索我们个人的微信公众号“程序员的成长之路”点击关注或扫描下方二维码

MySQL从删库到跑路_高级(五)——触发器的更多相关文章

  1. MySQL从删库到跑路_高级(七)——事务和锁

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.事务简介 1.事务简介 事务(Transaction)是指作为单个逻辑工作单元执行的一系列操作. 2.事物的特效 ...

  2. MySQL从删库到跑路_高级(六)——索引

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.索引简介 1.索引简介 索引(Index)是帮助MySQL高效获取数据的数据结构. 在MySQL中,索引属于存储 ...

  3. MySQL从删库到跑路_高级(四)——存储过程

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.存储过程简介 1.存储过程简介 存储过程是一组具有特定功能的SQl语句集组成的可编程的函数,经编译创建并保存在数 ...

  4. MySQL从删库到跑路_高级(二)——自定义函数

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.自定义函数简介 自定义函数(user-defined function UDF)是一种对MySQL扩展的途径,其 ...

  5. MySQL从删库到跑路_高级(一)——数据完整性

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.数据完整性简介 1.数据完整性简介 数据冗余是指数据库中存在一些重复的数据,数据完整性是指数据库中的数据能够正确 ...

  6. MySQL从删库到跑路_高级(三)——视图

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.视图简介 1.视图简介 视图是由SELECT查询语句所定义的一个虚拟表,是查看数据的一种非常有效的方式.视图包含 ...

  7. MySQL从删库到跑路(三)——SQL语言

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.SQL语言简介 1.SQL语言简介 SQL是结构化查询语言(Structured Query Language) ...

  8. MySQL从删库到跑路(五)——SQL查询

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 1.查询所有字段 在SELECT语句中使用星号“”通配符查询所有字段在SELECT语句中指定所有字段select f ...

  9. MySQL从删库到跑路(一)——MySQL数据库简介

    作者:天山老妖S 链接:http://blog.51cto.com/9291927 一.MySQL简介 1.MySQL简介 MySQL是一个轻量级关系型数据库管理系统,由瑞典MySQL AB公司开发, ...

随机推荐

  1. 【咸鱼教程】一个简单的弹出二级菜单UIPopupMenu

    一. 实际效果 演示地址 二.实现原理主要用Button+List组件,和遮罩实现. 1. 点击Button时,将List下移展开.2. 再次点击Button,或者选中List中的某一项时,将List ...

  2. 安装 SQL SERVER MsiGetProductInfo 无法检索 Product Code 1605错误 解决方案

    重装数据库服务器上的SQL SERVER 2008 上遇到了以下问题 标题: SQL Server 安装程序失败. SQL Server 安装程序遇到以下错误: MsiGetProductInfo 无 ...

  3. NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译

    NHibernate.3.0.Cookbook第一章第六节Handling versioning and concurrency的翻译   第一章第二节Mapping a class with XML ...

  4. 9.5Django

    2018-9-5 15:23:00 配置数据库信息  setting MySQLdb 不支持python3 创建表 pycharm 连接数据库 好强大的赶脚

  5. 从Spring到SpringBoot构建WEB MVC核心配置详解

    目录 理解Spring WEB MVC架构的演变 认识Spring WEB MVC 传统时代的Spring WEB MVC 新时代Spring WEB MVC SpringBoot简化WEB MVC开 ...

  6. 2018C语言第三次作业

    要求一 2.struct sk{int a; char *str)}*p;   p->str++ 中的++ 加向? ++加向srt的地址. 要求二 题目1-计算平均成绩 1.设计思路 (1)主要 ...

  7. 51nod 1183 - 编辑距离 - [简单DP][编辑距离问题][Levenshtein距离问题]

    题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1183 编辑距离,又称Levenshtein距离(也叫做Edi ...

  8. CCCC L2-022. 重排链表

    题解:直接list模拟,头尾两个指针,分别将头尾元素push到另一个list里面,输处输入方式同上一篇 坑:第一发卡了第二个样例,第二发卡了第4个,莫名其妙,所以把两个代码合起来,然后强行ac了. # ...

  9. h5地理位置API

    h5地理位置API 地理API允许javascript程序向浏览器询问用户的真实地理位置,支持地理位置API的浏览器在访问前总是会询问用户是否允许. 获取用户地理的途径有:         1.ip地 ...

  10. 01 - nginx - 安装、配置文件、默认网站、虚拟主机

    一.运维: . 介绍服务器. 服务器逻辑: 服务器选择 操作系统 部署逻辑 业务环境部署逻辑 业务部署图 软件部署文档 日常维护文档 测试 开发上传代码到源码系统 上线 - 测服务器,内测 预发布测试 ...