• SQL Server创建触发器


     

    为什么需要触发器<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

    为什么需要触发器(TRIGGER)呢?典型的应用就是银行的取款机系统 假定该系统的数据库设计需要两张表:帐户信息表(bank)存放帐户的信息,交易信息表(transInfo)存放每次的交易信息。

     

    上述结果有什么错误?您一定发现了,当张三取钱200元时,虽然交易信息表(transInfo)中保存了取钱200元的交易信息,但帐户表(bank)中的余额仍是1000,没有自动跟随修改。显然,我们应该根据交易类型是支取还是存入,自动减少或增加帐户表中的余额。而且,它还应该具有事务的特征:一旦交易失败,余额修改也应该自动取消 。那么,如何解决呢?这种特殊的业务规则使用普通约束行吗

    答案显然是否定的 。使用事务行吗?事务能保证一旦交易失败,余额修改也自动取消。但实现不了自动修改的触发功能 。所以,最优的解决方案就是采用触发器。触发器它是一种特殊的存储过程,并且也具有事务的功能,它能在多表之间执行特殊的业务规则或保持复杂的数据逻辑关系

     

    什么是触发器

    再看一个例子:目前有两张表,分别存放在职员工和退休员工的信息。

    假定现赵二退休:赵二将从员工表中删除。

    一旦删除赵二的信息,应自动触发一个动作:将赵二的信息保存到退休员工表中。

    强调:自动触发,而不是手动,如何实现呢,当然是使用触发器。

    q       触发器是在对表进行插入、更新或删除操作时自动执行的存储过程

    q       触发器通常用于强制业务规则

    q       触发器是一种高级约束,可以定义比用CHECK 约束更为复杂的约束

    q       可执行复杂的SQL语句(if/while/case

    q       可引用其它表中的列

    q       触发器定义在特定的表上,与表相关

    q       自动触发执行

    q       不像存储过程,不需要也不能人工调用执行

    q       本身就是一个事务,所以,如果发现有错误,可以回滚撤销操作。

     

    触发器的类型

    INSERT触发器:当向表中插入数据时触发,自动执行触发器所定义的SQL语句。

    UPDATE触发器:当更新表中某列多列时触发,自动执行触发器所定义的SQL语句。

    DELETE触发器:当删除表中记录时触发,自动执行触发器所定义的SQL语句。

     

      inserted deleted

    q       触发器触发时:

    q       系统自动在内存中创建deleted表或inserted

    q       只读,不允许修改;触发器执行完成后,自动删除

    q       inserted

    q       临时保存了插入或更新后的记录行

    q       可以从inserted表中检查插入的数据是否满足业务需求

    q         如果不满足,则向用户报告错误消息,并回滚插入操作

    q       deleted

    q       临时保存了删除或更新前的记录行

    q       可以从deleted表中检查被删除的数据是否满足业务需求

    q         如果不满足,则向用户报告错误消息,并回滚插入操作

    修改操作

    inserted

    deleted

    增加(INSERT)记录

    存放新增的记录

    ------

    删除(DELETE)记录

    -----

    存放被删除的记录

    修改(UPDATE)记录

    存放更新后的记录

    存放更新前的记录

    inserted表和deleted表存放的信息

     

    如何创建触发器

    创建触发器的语法:

    CREATE TRIGGER trigger_name

     ON table_name

     [WITH ENCRYPTION]

      FOR [DELETE, INSERT, UPDATE]

     AS

      T-SQL语句

    GO

    WITH ENCRYPTION表示加密触发器定义的SQL文本

    DELETE, INSERT, UPDATE指定触发器的类型

    insert触发器的工作原理:

    1.执行insert插入语句,在表中插入数据行;

    2.触发insert触发器,向系统临时表inserted表中插入新行的备份(副本)

    3.触发器检查inserted表中插入的新行数据,确定是否需要回滚或执行其他操作。

    问题:

    解决上述的银行取款问题:当向交易信息表(transInfo)中插入一条交易信息时,我们应自动更新对应帐户的余额。

     

    分析:

    l        在交易信息表上创建INSERT触发器

    l        inserted临时表中获取插入的数据行

    l        根据交易类型(transType)字段的值是存入/支取,

    l         增加/减少对应帐户的余额。

    CREATE TRIGGER trig_transInfo

     ON transInfo

      FOR INSERT

       AS

       DECLARE @type char(4),@outMoney MONEY

       DECLARE @myCardID char(10),@balance MONEY

       SELECT @type=transType,@outMoney=transMoney

             @myCardID=cardID FROM inserted /*inserted表中获取交易类型、交易金额等*/

         IF (@type='支取') /*根据交易类型,减少或增加对应卡号的余额 */

            UPDATE bank SET currentMoney=currentMoney-@outMoney

                 WHERE cardID=@myCardID

        ELSE

            UPDATE bank SET currentMoney=currentMoney+@outMoney

                 WHERE cardID=@myCardID

        …..

    GO

    delete触发器的工作原理:

    1.执行delete删除语句,删除表中的数据行;

    2.触发delete删除触发器,向系统临时表的deleted表中插入被删除的副本

    3.触发器检查deleted表中被删除的数据,确定是否需要回滚或执行其他操作。

    问题:

    当删除交易信息表时,要求自动备份被删除的数据到表backupTable

     

    分析:

    l        在交易信息表上创建DELETE触发器

    l        被删除的数据可以从deleted表中获取

    CREATE TRIGGER trig_delete_transInfo

     ON transInfo

      FOR DELETE

       AS

          print '开始备份数据,请稍后......'

          IF NOT EXISTS(SELECT * FROM sysobjects

               WHERE name='backupTable')

             SELECT * INTO backupTable FROM deleted/*deleted表中获取被删除的交易记录*/

         ELSE

             INSERT INTO backupTable SELECT * FROM deleted

          print '备份数据成功,备份表中的数据为:'

          SELECT * FROM backupTable

    GO

    UPDATE触发器的工作原理:

    执行更新操作,例如把李四的余额改为20001元。

    更新操作可以看出两步:

    1.删除李四原有的数据:李四 1000 0002  1,将数据备份到deleted表中。

    2.再插入新行:李四 1000 0002  20001将数据备份到inserted表中。

    最后看起来就是把余额从1修改为20001了。

    所以:如果我们希望查看修改前的原始数据,可以查看表deleted

    如果我们希望查看修改后的数据,可以查看表inserted

    问题:

    跟踪用户的交易,交易金额超过20000元,则取消交易,并给出错误提示。

     

    分析:

    l        bank表上创建UPDATE触发器

    l        修改前的数据可以从deleted表中获取

    l        修改后的数据可以从inserted表中获取

    CREATE TRIGGER trig_update_bank

     ON bank

      FOR UPDATE

       AS

          DECLARE @beforeMoney MONEY,@afterMoney MONEY 

    /*deleted表中获取交易前的余额,从inserted表中获取交易后的余额*/

          SELECT @beforeMoney=currentMoney FROM deleted  

          SELECT @afterMoney=currentMoney FROM inserted   

          IF ABS(@afterMoney-@beforeMoney)>20000 /*交易金额是否>2*/

            BEGIN

                print '交易金额:'+convert(varchar(8),

                    ABS(@afterMoney-@beforeMoney))

                RAISERROR ('每笔交易不能超过2万元,交易失败',16,1)

                ROLLBACK TRANSACTION /*回滚事务,撤销交易*/

             END

    GO

    列级 UPDATE 触发器

    q       UPDATE触发器除了跟踪数据的变化(修改)外,还可以检查是否修改了某列的数据

    q       使用UPDATE()(列)函数检测是否修改了某列

    问题:

    交易日期一般由系统自动产生,默认为当前日期。为了安全

    起见,一般禁止修改,以防舞弊。

     

    分析:

    UPDATE(列名)函数可以检测是否修改了某列

    CREATE TRIGGER trig_update_transInfo

     ON transInfo

      FOR UPDATE

       AS

          IF UPDATE(transDate)/* 检查是否修改了交易日期列transDate*/

             BEGIN

                print '交易失败.....'

                RAISERROR (‘安全警告:交易日期不能修改,

                               由系统自动产生',16,1)

                ROLLBACK TRANSACTION   /*回滚事务,撤销交易*/

             END

    GO

     

    好,我们来做个总结:

    q       触发器是在对表进行插入、更新或删除操作时自动执行的存储过程,触发器通常用于强制业务规则

    q       触发器还是一个特殊的事务单元,当出现错误时,可以执行ROLLBACK TRANSACTION回滚撤销操作

    q       触发器一般都需要使用临时表:deleted表和inserted表,它们存放了被删除或插入的记录行副本

    q       触发器类型:

    q        INSERT触发器

    q        UPDATE触发器

    q        DELETE触发器

     

  • 相关阅读:
    LeetCode 24. Swap Nodes in Pairs (两两交换链表中的节点)
    LeetCode 1041. Robot Bounded In Circle (困于环中的机器人)
    LeetCode 1037. Valid Boomerang (有效的回旋镖)
    LeetCode 1108. Defanging an IP Address (IP 地址无效化)
    LeetCode 704. Binary Search (二分查找)
    LeetCode 744. Find Smallest Letter Greater Than Target (寻找比目标字母大的最小字母)
    LeetCode 852. Peak Index in a Mountain Array (山脉数组的峰顶索引)
    LeetCode 817. Linked List Components (链表组件)
    LeetCode 1019. Next Greater Node In Linked List (链表中的下一个更大节点)
    29. Divide Two Integers
  • 原文地址:https://www.cnblogs.com/CharmingDang/p/9663725.html
Copyright © 2020-2023  润新知