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

    go
    --请判断下面的两条sql语句来业务逻辑上是否合理
    --第一条:新增会员卡,会员卡开通时间:2012-7-1
    insert into tblcardinfo
    (chvUserName,chvPassword,mnyBalance,dtmRegisterTime)
    values
    ('dujiu', '123456', 50, '2012-7-1')
    go
    select * from tblcardinfo;
    --第二条:新增上机记录,其中开始上机时间:2012-5-1
    insert into tblrecordinfo
    (intComputerId,intCardId,dtmStart,dtmEnd,mnyFee)
    values
    (1, 4, '2012-5-1', '2012-5-1', 2)
    go
    select * from tblrecordinfo;
    go
    --虽然上面两条语句都能执行成功,但是错误的业务逻辑也很明显:
    --2012年开通的会员卡怎么可能存在2012-5-1的上机记录呢???

    --使用我们之前学过的检查约束,看能够解决这个问题

    alter table tblrecordinfo
    add constraint ck_recordinfo_dtmStart check (dtmStart>TblCardInfo.dtmRegisterTime)

    --上面添加的检查约束无法被创建
    --原因是:检查约束中被检查的字段只能来源于当前表,而不能从其他表中判断
    --我们前面学过的任何约束都无法实现这一功能性约束!!!
    --对于这种问题,我们的解决办法就是:触发器

    -----------触发器-------------------------

    --待解决的问题:向tblrecordinfo表中新增记录时,上机开始时间必须要大于会员卡注册时间


    --
    /*
      inserted介绍
      1.inserted是一张临时表
      2.改表只有在触发器被执行时才起作用
      3.inserted表结构是怎样的:它和被操作的表结果完全一致

    */

    --如何删除触发器
    drop trigger tr_insertRecord
    go
    --如何定义|创建一个触发器
    create trigger tr_insertRecord
    on TblRecordInfo
    for insert--for等价于after,表示当新增完记录之后才会执行触发器
    as
    begin
      declare @cardid int, @startTime datetime;
      select @cardid = intcardid, @startTime = dtmStart from inserted;
      select '卡号:'+convert(nvarchar(5), @cardid);
      select '上机开始时间:'+convert(nvarchar(20), @startTime);
    end

    --如何修改触发器
    alter trigger tr_insertRecord
    on TblRecordInfo
    for insert
    as
    begin
      --定义变量:会员卡号、开始上机时间、会员卡注册时间
      declare @cardid int, @startTime datetime, @registerTime datetime;
      --从inserted表中提取会员卡号、开始上机时间。此时的inserted表结构和TblRecordInfo一致
      select @cardid = intcardid, @startTime = dtmStart from inserted;
      --根据会员卡id从会员卡信息表中提取该卡的注册时间
      select @registerTime = dtmRegisterTime from tblcardInfo where intcardid=@cardid;
      --比较会员卡注册时间和上机时间
      if(@registerTime>@startTime)
      begin
        --不满足时进行事务回滚:使insert into tblrecord......无法真正被执行
        rollback transaction
      end
    end

    --使用insert向tblrecordinfo新增记录,验证触发器是否会执行
    insert into tblrecordinfo
    (intComputerId,intCardId,dtmStart,dtmEnd,mnyFee)
    values
    (1, 4, '2012-7-15', '2012-7-15', 2)

    select * from tblcardinfo
    go

    select * from tblrecordinfo
    go

    delete from tblcomputer where intcomputerid=1;

    alter trigger tr_deletecomputer
    on tblcomputer
    --for delete
    instead of delete
    as
    begin
      declare @computerid int;
      select @computerid=intcomputerid from deleted;
      delete from tblrecordinfo where intcomputerid = @computerid;
      delete from tblcomputer where intcomputerid = @computerid;
    end

    delete from tblcomputer where intcomputerid=1;

    --张三换电脑:2-------->3
    insert into tblrecordinfo
    (intComputerId,intCardId,dtmStart,dtmEnd,mnyFee)
    values
    (2, 1, '2012-7-21', '2012-7-21', 2)

    select * from tblrecordinfo

    alter trigger tr_updaterecordinfo
    on tblrecordinfo
    for update
    as
    begin
      declare @oldcomputerid int, @newcomputerid int;
      if update(intcomputerid)
      begin
        select @oldcomputerid = intcomputerid from deleted;
        select @newcomputerid = intcomputerid from inserted;
        update tblcomputer set intinuse = 1 where intcomputerid =@newcomputerid
        update tblcomputer set intinuse = 0 where intcomputerid =@oldcomputerid
      end
    end

    select * from tblcomputer
    update tblrecordinfo set intcomputerid = 3 where intrecordid=19
    select * from tblcomputer

  • 相关阅读:
    test!
    Visual Studio 中的单元测试 UNIT TEST
    Jquery结合div+css实现文字间断停顿向上滚动效果
    asp.net中使用HttpWebRequest发送上传文件
    分享一个可以灵活控制的实现Javascript滚动效果的程序
    VeryCodes.Log让日志记录和读取变的更简单
    实现MyXLS设置行高的功能
    设计模式学习笔记建造者模式
    设计模式学习笔记原型模式
    设计模式学习笔记模板方法
  • 原文地址:https://www.cnblogs.com/changjiang/p/2605305.html
Copyright © 2011-2022 走看看