MySQL(5)-mysql的事务与触发器功能

         本篇博客介绍的是MySQL的事务功能和触发器功能 , 以及它们的用法 .


 一 . MySQL事务

         

        事务是一组原子性的SQL查询,或者说是一个独立的工作单元。事务中的所有操作要么全部执行成功,要么全部执行失败

        在MySQL中 , 采用事务功能可以实现有选择性的对表中的数据操作做回滚 , 提交 , 类似于word中的记忆功能 (做错了可以CTRL+Z撤销)

        MySQL默认处理任务的原则 : 执行增 , 删 , 改操作会自动保存数据到库 , 表记录中

        生活实例 : 好比玩游戏 , 当玩家在玩游戏充值时 , 假如钱扣了 , 道具却没有立即到手 , 这样显然会大大减低玩家对游戏的体验 , 最后导致的双方的不开心 ,出现这种情况说的就是数据的事务没有保障 ; 假如出现这种情况事务功能可以解决这种问题 , 也就是道具没有到账的情况 , 玩家账户的余额也是不会扣除的


         MySQL的事务处理主要有两中方法:


         1 . 用BEGIN , ROLLBACK , COMMIT 来实现

              begin : 开始一个事务 , 然后执行create , update , insert等命令对数据做出操作 

              rollback : 事务回滚 (相当于word中的ctrl+z撤销)

              commit : 事务确认 (提交 , 相当于word中的ctrl+s保存)    


          2 . 通过set来改变mysql的自动提交模式

               注 : MYSQL默认是自动提交的,也就是你提交一个QUERY,它就直接执行!我们可以通过
               show   variables \G        查看MYSQL环境变量
               show   variables  like  'autocom%';     查看autocommit环境变量的状态
               set  autocommit=0   禁止自动提交(临时设置) ,即自动开启事务功能,并不需要用begin开始事务,但是必须用commit提交操作,或用rollback撤消操作 , 此时查看autocommit环境变量  , value为OFF:

                 image.png

               set autocommit=1   开启自动提交(必须用begin开始一个事务,用commit或rollback结束事务)来实现事务的处理 .查看auto commit值为状态ON .
                 

               但注意当你用 set autocommit=0 的时候,你以后所有的SQL都将做为事务处理,直到你用commit确认或rollback结束,当你结束这个事务的同时也开启了个新的事务!按第一种方法只将当前的作为一个事务!个人推荐使用第一种方法!
               MYSQL中只有INNODB和BDB类型的数据表才能支持事务处理!其他的类型是不支持的!
               注意:事务功能只对表的insert、delete、update这些操作有效。


   实例 : 进入数据库中 , 使用test数据库 , 创建一张testdb表 , 查看表中的数据 , 然后开启事务功能 , 插入2条数据 , 提交事务 , 查看表中的数据 ; 然后开启新事务 , 插入一条记录 , 做回滚操作(撤销) , 查看表中的数据

              

              第一步 : 在test数据库中创建testdb表 , 查看表中数据

              image.png

              第二步 : 开启事务功能 , 并插入数据 ,然后提交

              image.png

              第三步 : 开启新事务 , 插入一条记录 , 做回滚操作(撤销) , 并查看表中的数据

              image.png




 二 . mysql触发器功能


        触发器(trigger)是一个特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件(event)来触发,
        比如当对A表进行操作事件( insert,delete, update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务规则等

        用生活实例来说 : 在A处按电脑开机键,电脑就开机了。
                                    在A处按灯的开关,B处天花板上的灯就亮了。

                                    在A处打卡 , 通道门就开了

        创建触发器(trigger)语法 :

                   CREATE  TRIGGER  触发器名称  BEFORE|AFTER  触发事件

                   ON  表名 FOR  EACH  ROW

                   BEIGN

                           触发器程序体 ;

                   END  

                 <触发器名称> 最多64个字符,它和MySQL中其他对象的命名方式一样
                 { BEFORE | AFTER } 触发器时机
                 { INSERT | UPDATE | DELETE }   触发的事件
                 ON <表名称>   标识建立触发器的表名,即在哪张表上建立触发器
                 FOR EACH ROW        触发器的执行间隔:FOR EACH ROW子句通知触发器 每隔一行 执行一次动作,而不是对整个表执行一次
                 <触发器程序体> 要触发的SQL语句:可用顺序,判断,循环等语句实现一般程序需要的逻辑功能

        

    实例 : 在test数据库中创建一张stu学生表和一张统计stu表的人数的stu_total表  , 然后创建student表发生改变 , stu_total表就发生改变的触发器 , 对stu表进行操作 , 然后查看stu_total因触发器会有什么变化


              第一步 :创建这两张表 , 并查看表中的数据

              image.png

              第二步 : 创建触发器stu_insert_trigger 和触发器stu_delete_trigger

              image.png

              第三步 : 再次定义回操作结束符( ; ) ,并查看触发器

              image.png

              第四步 : 检测触发器结果

               image.png

               第五步 : 对stu表进行delete操作 , 再次验证实验效果

               image.png

            

       从实验结果可以看到 , 当我们对stu表进行数据的增删操作时 , 定义触发器后 , stu_total表会根据stu表的不同操作发生不同变化 !

        

       删除触发器 :  DROP TRIGGER 解发器名称

     

       注 :此例的触发器故障bug:如果stu_total表中的初始统计数据不正确,以上定义的这个触发器会导致stu_total表中统计的total值跟stu表中的总记录数信息不对称,所以这个触发器是有问题的。正确的解法是用count函数来统计stu表中的记录数,不应该用加1或减1这种做法。


      优化过的正确触发器:

      触发器stu_insert_trigger

      drop  triggers  stu_insert_trigger;

      delimiter   $$

      create trigger stu_insert_trigger  after insert

          on stu for each row

          BEGIN

               update stu_total set total=(select  count(*)  from  stu);

          END$$

      delimiter  ;


      触发器stu_insert_trigger

      drop   trigger stu_insert_trigger;

      delimiter   $$

      create trigger stu_insert_trigger  after insert

         on stu for each row

         BEGIN

             update stu_total set total=(select  count(*)  from  stu);

         END$$

       delimiter  ;

       

              

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章