zoukankan      html  css  js  c++  java
  • SQL中触发器的使用

    创建触发器 是特殊的存储过程,自动执行,一般不要有返回值

    类型:

      1.后触发器 (AFTER,FOR)先执行对应语句,后执行触发器中的语句

      2.前触发器  并没有真正的执行触发语句(insert,update,delete),而是执行触发后的语句

      3.行级触发器 (FOR EACH ROW) 在SQL server 中不存在

    商品号为1的库存量:

    1.后触发器(实现不同表之间的约束)

    --实现在销售量不大于库存量时,每卖出n件商品,对应商品的库存要减n,若销售量大于库存量,则回滚此次操作
    IF EXISTS (SELECT *FROM sysobjects WHERE name='tr_SaleCommodity')
        DROP TRIGGER tr_SaleCommodity
    GO
    CREATE TRIGGER tr_SaleCommodity
    ON OrderInfo FOR INSERT  --FOR/AFTER为后触发器
    AS
        BEGIN
            IF EXISTS (
                SELECT  * FROM inserted I INNER JOIN CommodityInfo C ON I.CommodityId=C.CommodityId
                WHERE I.Amount>C.Amount
            )
                BEGIN
                    ROLLBACK  --后触发器
                    PRINT '商品的销售量大于商品的库存量'
                END    
            ELSE
                BEGIN
                    UPDATE CommodityInfo
                    SET Amount=Amount-(SELECT Amount FROM inserted)
                    WHERE CommodityId IN
                    (
                        SELECT CommodityId FROM inserted
                    )
                END
        END
    GO

    执行:

    INSERT INTO OrderInfo(UserId,CommodityId,Amount,PayMoney,PayWay,OrderTime,Confirm,SendGoods)
    VALUES('YOUYOU',1,10,600,'网上银行','2014-11-11 00:00:00.000',1,1)

    结果:

      注意:1.上一行为销售记录,下一行为商品1的信息

         2.卖出10个,库存量由48变为38 

           3.可以看出以上的销售记录中的Paymoney是不正确的,它的值应该是Amount*OutPrice=10*300,所以需要前触发器来约束

    2.前触发器(可以实现行级触发器功能)

    --实现了日期校验和支付金额的计算
    IF EXISTS(SELECT* FROM sysobjects WHERE name='tr_DateConfim')
        DROP TRIGGER tr_DateConfim
    GO
    CREATE TRIGGER tr_DateConfim
    ON OrderInfo INSTEAD OF INSERT ,UPDATE
    AS
        BEGIN
            DECLARE @date datetime
            SELECT @date=OrderTime FROM inserted
            IF @date BETWEEN '2012-1-1' AND '2015-1-1'
                BEGIN
                    DECLARE @UserId varchar(20) ,@CommodityId int,@Amount int,@PayMoney money,@PayWay varchar(20),@OrderTime datetime,@Confirm int,@SendGoods int
                    SELECT @UserId=UserId,@CommodityId=CommodityId,@Amount=Amount,@PayWay=PayWay,@OrderTime=OrderTime,@Confirm=Confirm,@SendGoods=SendGoods FROM inserted
                    DECLARE @outPrice money
                    SELECT @outPrice=OutPrice FROM CommodityInfo WHERE CommodityId=@CommodityId
                    SET @PayMoney=@outPrice*@Amount
                    PRINT 'inserted 中的数据:'+CONVERT(varchar(20),@UserId)+' '+CONVERT(varchar(20),@CommodityId)+' '+CONVERT(varchar(20),@Amount)+' '+CONVERT(varchar(20),@PayMoney)+' '+CONVERT(varchar(20),@PayWay)+' '+CONVERT(varchar(20),@OrderTime)+' '+CONVERT(varchar(20),@Confirm)+' '+CONVERT(varchar(20),@SendGoods)+' '+CONVERT(varchar(20),@outPrice)
                    INSERT INTO OrderInfo(UserId,CommodityId,Amount,PayMoney,PayWay,OrderTime,Confirm,SendGoods)
                    SELECT UserId,CommodityId,Amount,@PayMoney,PayWay,OrderTime,Confirm,SendGoods FROM inserted
                END
            ELSE 
                PRINT '你插入的数据中的时间只能在 2012-1-1 到 2015-1-1 中间'
        END
    GO

    执行:

    INSERT INTO OrderInfo(UserId,CommodityId,Amount,PayWay,OrderTime,Confirm,SendGoods)
    VALUES('YOUYOU',1,5,'网上银行','2013-1-11',1,1)

       注意:这里插入时我并没有定义PayMoney,PayMoney是通过触发器来自动计算的

    结果:

    日期不正确:

    日期正确:

    打印信息对应:@UserId+' '+@CommodityId+' '+@Amount+' '+@PayMoney+' '+@PayWay+' '@OrderTime+' '@Confirm+' '+@SendGoods+' '@outPrice

    3.行级触发器(错误

      

    执行结果:

    可以看出在SQL server中并不支持行级触发器

  • 相关阅读:
    B树/[oracle]connect BY语句
    使用vmware vconverter从物理机迁移系统到虚拟机P2V(多图)
    goldengate常用命令
    GoldenGate 之 Bounded Recovery说明
    RAC环境中threads变更后如何确保goldengate继续正常复制
    简述Oracle IOT(Index Organized Table)
    mybatis-spring最新版下载地址
    12 个 CSS 高级技巧汇总
    Linux命令:useradd
    PHP date()函数详解
  • 原文地址:https://www.cnblogs.com/feiquan/p/8685722.html
Copyright © 2011-2022 走看看