mysql高级:触发器

来源:互联网 发布:天津商业大学网络缴费 编辑:程序博客网 时间:2024/06/04 17:48
有时会碰到表的某些数据改变,希望同时引起其他相关数据改变的需求,利用触发器就可以满足这样的需求。
它能在表中的某些特定数据变化时自动完成某些查询。
运用触发器不仅可以简化程序,而且可以增加程序的灵活性。


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


触发器创建语法


    4要素
        监视地点(table)
        监视事件 insert、update、dalete
        触发时间 after、before
        触发事件 insert、update、dalete


* 触发器引用行变量


    insert new 新行 (监控新增的一条数据)
    delete old 旧行 (监控删除的一条数据)
        引用
            new.字段名
            old.字段名
    update old->new 改前到改后 (监控修改一条数据)




查看触发器:
    show triggers
删除发触发:
    drop trigger triggerName


触发器 trigger:


    需求:
        商品表: goods
        订单表: ord


        当有新订单、修改订单、删除订单操作时,对应的商品要相应减少(买几个商品就少几个库存)


    分析:


        操作:新订单
        监视:ord
        监视动作:insert
        触发时间:after
        触发事件:update


        操作:删除订单
        监视:ord
        监视动作:delete
        触发时间:after
        触发事件:update


        操作:修改订单
        监视:ord
        监视动作:update
        触发时间:before
        触发事件:update


    创建表
    CREATE TABLE `ord` (
        `oid` int(10) NOT NULL auto_increment,
        `gid` int(10) DEFAULT NULL,
        `much` int(10) DEFAULT NULL,
        PRIMARY KEY (`oid`)
    );




    CREATE TABLE `goods` (
      `gid` int(11) NOT NULL auto_increment,
      `name` varchar(20) DEFAULT NULL,
      `num` smallint(6) DEFAULT NULL,
        PRIMARY KEY (`gid`)
    );


    insert into goods values(1,'cat',34),(2,'dog',65),(3,'pig',21);






    触发器
    //设置mysql定界符为$  因为begin里的sql用';'结尾。 如多行情况下,让mysql分开每条sql语句,而不结束
    delimiter $ 
    //有新订单时
    create trigger ordAdd
    after insert
    on ord
    for each row
    begin
    update goods set num = num-new.much where gid = new.gid;
    end$


    //删除订单时
    create trigger ordDel
    after delete
    on ord
    for each row
    begin
    update goods set num = num+old.much where gid = old.gid;
    end$
   
    //改订单时
    create trigger ordUp
    before update
    on ord
    for each row
    begin
    update goods set num = num+old.much-new.much where gid = old.gid;
    end$






# 思考: before目前似乎没有看出与after的区别


# 再思考: 如果剩余3头猪,但客户买了10头,发生什么情况?能否预防?
# 能否在购买量much > 库存量num时,把much自动改为num
# 提示 before


    create trigger ordAdd
    before insert
    on ord
    for each row
    begin
        declare //声明变量
        rnum int; //变量rnum为INT型


        //将查询出来的num赋给变量rnum
        select num into rnum from goods where gid = new.gid;
        //判断
        if rnum < new.much then
            set new.much = rnum;
        end if
        update goods set num = num-new.much where gid = new.gid;
    end$






# 触发器(trigger)中 for each row 是什么意思


    在oracle触发器中,触发器份语句级触发器和行级触发器。


    for each row 是行级触发器
        例如
            after|before update
            update影响了100行数据,那么sqlN会被触发100次。
            
    在oracle中 for each row 如果不写,无论update语句一次影响了多少行数据,都只执行1次。


    比如:1人下了订单,买了5件商品,insert 5次,可以用行级触发器修改5次库存。


    用语句触发器,insert一条发货提醒。


    遗憾的是 mysql目前不支持语句触发器。


    所以在mysql触发器(trigger)中for each row必须写。
0 0