zoukankan      html  css  js  c++  java
  • MySQL触发器

    触发器是一类特殊的事务,可以监视某种数据操作(insert,update,delete),并触发相关操作(insert,update,delete)

    触发器创建之四要素:

      监视地点

      (table)

         监视事件

    (insert,update,delete)

      触发时间

    (after,before)

         触发事件

    (insert,update,delete)

    举个例子,有两张表,分别是商品表goods和订单表ord

    当下一个订单的时候,对应的商品要相应减少(买几个商品就少几个库存)

    分析:

    监视谁:ord

    监视动作:insert

    触发时间:after

    触发事件:update

    那么就来写创建触发器的语法:

    delimiter $     (这是指定程序碰见$才结束,而不是以分号结束)

    create trigger 触发器名称

    after/before(触发时间)

    insert/update/delete(监视事件)

    on 表名(监视地址)

    for each row

    begin

    sql1;

    ...

    sqlN;

    end $

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

    我们可以看到我们的商品表已经创建好了:

    然后我们下订单:

    我想买3只猫,那么我们用触发器来实现这个操作:

    create trigger t2
    after
    insert
    on ord
    for each row
    begin
    update goods set num=num-new.much where gid=new.gid;
    end$

    我们可以看到订单表是空的,然后我们给里面插入数据:

    然后我们去看看商品表里面的库存变了没:

    我们可以看到猫的库存确实减少了三只

    那我们想删除一个订单,退货,那么库存就应该再加回去,应该怎么做?

    我们新建一个触发器,监视删除订单的操作:

    create trigger t3
    after
    delete
    on ord
    for each row
    begin
    update goods set num=num+old.much where gid=old.gid;
    end$

    上面是原来的订单和库存,下面是我们执行删除订单后的数据,没有任何问题:

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

    那我们想修改订单,我们想把上面的订单买的猫数量改一下:我想买1只猫,三只猫太多了养不过来。

    那我们建立一个新的触发器来监视订单的修改:

    create trigger t4
    before
    update
    on ord 
    for each row
    begin
    update goods set num=num+old.much-new.much where gid=new.gid;
    end$

    这是改订单之前我们的库存。

    然后我们来改订单:

    update ord set much=1 where oid=1$

    我们可以看到猫的数量变成了33,这证明我们写的触发器没有问题。

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

    那么我们再思考,如果购买的数量超过库存应该怎么办?能不能预防?

     假设我们有个大客户他下了一个订单想买25头猪:

    我们增加一个订单:

    insert into ord values(2,3,25)$

    我们看到这个订单确实被增加进去了,但是库存呢?

    我们看到这个猪的库存变成了-4,这种情况叫爆仓,这是不允许发生的,那么我们怎么预防它?

    我们建立一个判断,如果new.much的值>num,那么我们把new.much=num

    我们把原来的t2触发器删掉,新建一个t5触发器:

    create trigger t5
    before
    insert
    on ord 
    for each row
    begin
    declare 
    rnum int;
    select num into rnum from goods where gid=new.gid;
    if new.much>rnum then
        set new.much=rnum;
    end if;
    update goods set num=num-new.much where gid=new.gid;
    end$

    注意一定要用before,否则会报下面的错误:

    这是我们的库存,接下来我们生成一个订单,买25头猪:

    我们可以看到库存已经为0;

    订单表也显示只买了21头猪。

     这证明我们的触发器确实发挥了作用。

    然后我们看到我们的触发器语句里面有for each row,那么它是干啥的?

    举个例子:

    我们建立一个新表:

    我们创建一个触发器:每当ord的数据被修改,我们就往tmp表插入一个5

    create trigger t9
    after
    update
    on
    ord
    for each row
    begin
    insert into tmp values(5);
    end$

    我们看到我们的tmp现在是空的,我们接下来修改ord表中的值:

    然后我们去看看tmp表有何变化:

    我们可以看到tmp表一次被增加了两条数据。

    这就是for each row的作用:它是声明 每一行受影响,触发器都触发一次,这种触发器也叫行级触发器。mysql暂时不支持语句级触发器

  • 相关阅读:
    vue3.0中如何使用ueditor
    如何在vue+element中实现选择框和穿梭框的根据拼音以及拼音首字母以及汉字的模糊搜索
    select 使其默认选中文本不为空
    java环境配置
    amaze ui 滚动监听
    vue项目中如何使用less
    强大的css3库
    input type file兼容性
    select中想要加a链接 并且新窗口打开
    echarts绘制k线图为什么写candlestick类型就报错
  • 原文地址:https://www.cnblogs.com/wanghaoyu666/p/11309832.html
Copyright © 2011-2022 走看看