作者:天山老妖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. .NET 高性能WEB架构-比较容易改造方式 - .NET架构

    下面列出的一些,是我们常见而且比较容易去优化的方式,当然细节方面非常多,仅供参考: 1.数据库依然选择SQL Server数据库(最新的sqlserver功能是很强大的)和使用订阅发布进行单写多读的读 ...

  2. Java内存泄露监控工具:JVM监控工具介绍【转】

    jstack?-- 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程 ...

  3. Power Shell 学习笔记

    Powershell 是运行在windows机器上实现系统和应用程序管理自动化的命令行脚本环境. 桌面右击任务栏开始图标,打开控制台对话窗: Windows PowerShell ISE 应用程序的文 ...

  4. 访问php文件显示源码

    前天新装了个LAMP的环境,兴冲冲的clone下来代码,结果一访问乐子就大了,直接显现源码 面对这个问题,冥思苦想,四处找资料啊 让我改这改那的,最后终于找到症结 Ubuntu 16.04 系统 LA ...

  5. Web开发中需要了解的东西【转载】

    在StackExchange上有人问了这样一个问题:What should every programmer know about web development?(关于Web开发,什么是所有程序员需 ...

  6. hdu3038 How many answers are wrong【并查集】

    TT and FF are ... friends. Uh... very very good friends -________-b  FF is a bad boy, he is always w ...

  7. cordova 跨平台APP版本升级

    利用cordova+ionic开发好项目,之后就是打包发布,在这之前,还要做一个版本升级的小功能. 首先我们项目根目录里自然少不了配置:config.xml中 如图.version,我们以后每次升级A ...

  8. 2018/03/27 每日一个Linux命令 之 cron

    Cron 用于配置定时任务. -- 环境为 Ubuntu16-04 -- 先说说怎么配置一个简单的定时任务.直观的可以看到效果. 之前在网上查找资料,对Shell编程不熟悉的实在是很头疼,走了不少弯路 ...

  9. LoadRunner-参数化(参数间关联)

    多用户测试,每个用户账号对应一个密码,账号和密码需要一 一关联才能登录成功. 1.在已经对账号进行参数化后,选中密码的值->右键选择Replace with a Parameter,参数名为pa ...

  10. RSA原理说明

    长度,建议至少1024.模数n(常取默认65537)两边都要用. 指数e,和n一起就是公钥. 指数d,和n一起就是私钥. 质数p和q用于生成密钥对,然后就丢弃不公开. 一.密钥对的生成步骤 1.随机选 ...