mysql学习之旅-之使用-1.2.3-之触发器

1、触发器简介
触发器就是在执行增删改时自行执行的sql语句,是存储在数据库目录中的
2、触发器的优缺点
优点: 
      1、减少后台频繁访问数据库
      2、安全性:可以基于数据库的值是用户具有操作数据库的某种权限,可以基于时间限制用户操作(例不允许下班后和节假日修改数据库数据),可以基于数据库中的数据限制用户的操作(例如不允许股票的价格的升幅一次超过10%)
      3、完整性:具有任务回滚的能力
      4、同步实时复制数据
缺点:
      1、如果需要变动整个数据集而数据集数据量又较大时,触发器效果会非常低
      2、触发器执行过程不可见,出现问题及其难查
      3、数据库的移植性较差,维护较难        
3、触发器的使用
A、创建触发器

CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmt

trigger_name:触发器的名称。
tirgger_time:触发时机,为BEFORE或者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索引时,如果插入的数据和原来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赋值,不会再次触发触发器,造成循环调用。

B、删除触发器

DROP TRIGGER 触发器名称

C、查看触发器

SHOW TRIGGERS

4、应用
A、业务逻辑

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

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);

在这里插入图片描述

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

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

插入订单

INSERT INTO orders(pid, onum)VALUES(13, 10);

查看产品表,可以看到对应的产品数量减少。操作由订单表的Insert触发器完成。
在这里插入图片描述

在订单表上创建新的触发器,当订单定的某产品产品数量大于产品库存,禁止下订单,也就是禁止在订单表中插入记录。
一张表中只能有一个INSERT类型的触发器,先删除INSERT触发器。

drop trigger trigger_order;

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

create trigger trigger_order
BEFORE INSERT ON orders FOR EACH ROW
BEGIN
DECLARE 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

   SELECT pnum INTO var FROM product where pid=NEW.pid;  用来查询为更新前的数据赋值给 var 使用INTO

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

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

B、实现安全

①限制插入记录的日期
在订单表上创建插入触发器,周六周日不允许下订单(记得一个表只能有一个insert触发器)

create trigger trigger_limitDate
BEFORE INSERT ON orders FOR EACH ROW
BEGIN
DECLARE 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)

②限制数据更改的范围
在产品表上创建更新触发器,限制产品价格一次上调不能超过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;

C 实现数据完整性

使用触发器可以限制表插入某列的数值范围。
创建一个学生表,有四列,姓名、性别、手机和邮箱。

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

①指定性别列的取值范围
创建触发器,限制性别列,只允许输入“男”和“女”。before insert触发器,不满足条件执行有错误的SQL语句,退出。

create trigger trigger_limitSex
before insert on personinfo for each row
begin
declare 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’); 正确

②限制手机列的取值类型和长度
创建触发器,只允许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’); 错误 (首位值)
nsert into personinfo VALUES(‘唐僧’, ‘男’,‘18900000001’); 错误 (值位数不对)

D使用触发器审计

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

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

①创建触发器记录插入操作

create trigger trigger_insert
before insert on personinfo for each row
begin
insert into review values(user(),‘insert’,new.sname,now());
End

插入personinfo表一条记录

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

查看review表中增加的INSERT记录
在这里插入图片描述
②创建触发器记录删除操作

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记录
在这里插入图片描述

③创建触发器记录修改操作

create trigger trigger_update
after UPDATE on personinfo for each row
begin
insert review values(user(),‘update’,new.sname,now());
End

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

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

查看reivew表中增加的UPDATE记录
在这里插入图片描述

转自:http://blog.51cto.com/9291927/2095105

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值