触发器,当我们在对一个表进行增删改操作后,可以自动的对相关联的表进行一些默认的操作。
DELIMITER $ #设置结束标识符 create trigger t1 #设置触发器的名称 after #触发的顺序,在当前sql执行之前还是在之后来执行该触发器。after/before insert #触发的条件,当前是添加操作,共有insert/update/delete三种 on ord #当操作张表的时候触发 ord 表名 for each row #没执行一行都会触发一次,叫做行触发器 begin update goods set num = num - new.much where id = new.gid; #触发后执行的sql end$
一个简单的触发器。修改结束定界符, 是因为mysql 默认是遇到 ; 就结束。但是 begin 后的sql 也是;结束。就导致触发器意外的结束,触发器语法错误的情况。所以把结束的定界符修改后就可以解决。
例子:
新建一个商品表,和订单表。
#商品表 create table goods(id int,name varchar(35),num int) #订单表 create table ord(id int,gid int,much int); #商品表添加信息 insert into goods values(1,'dog',43),(2,'pig',45);
当我们下一个订单后希望自动,去修改商品表的库存。
用我上面的的t1触发器就可以来实现,但是不严谨。可能会出现卖超的情况。
下面我们讲一下,添加、删除、修改 如何在触发器中获取他们操作的对应记录的。
添加:
添加用 new 来表示新增。
删除 :
删除用 old 来表示删除
修改
修改是用 old 到 new 的过程。 old(旧的数据)->new(新的数据)。
new和old中保存的都是对应某一条数据(也就是一个数组)。
当我们删除一条订单的时候,应该吧对应的商品库存加上
create trigger t2 #设置触发器的名称 after #触发的顺序,在当前sql执行之前还是在之后来执行该触发器。after/before delete #触发的条件,当前是添加操作,共有insert/update/delete三种 on ord #当操作张表的时候触发 ord 表名 for each row begin update goods set num = num + old.much where id = old.gid; #触发后执行的sql end$
我们接着来说如何解决,卖超的现象吧。
我们在下订单的时候去获取一下该订单的库存,然后进行比较超出就把订单数改成库存数。(主要是了解 触发器中的使用 if操作和after/before的差异性)
create trigger t2 after insert on ord for each row begin declare #声明一个变量 rnum int; select num into rnum from goods where id = new.gid; # select...into...吧查询出的值赋值给一个变量 if new.much > rnum then #if判断 set new.much = rnum ; end if; #if判断结束 update goods set num = num - new.much where id = new.gid; end$
在上面我用的是after来声明的,这时候你会看到报了一条错误:
ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger
这里就体现到after和before的差别了。
我们不能再sql执行完成之后再对这条语句进行值得改变。
所以需要把after 改成 befroe,在他执行前去执行触发器
create trigger t2 before insert on ord for each row begin declare rnum int; select num into rnum from goods where id = new.gid; if new.much > rnum then set new.much = rnum ; end if; update goods set num = num - new.much where id = new.gid; end$
所以我们可以根据我们的业务逻辑,在触发器被触发时,执行一些需要的业务操作。