美文网首页
09-17:触发器

09-17:触发器

作者: 神坛下的我 | 来源:发表于2018-09-17 13:51 被阅读0次
    • 触发器,存储过程,自定义函数,事务,自动备份
    • 数据库完整性
    1. 主键约束 primary key
      实体完整性(唯一约束+非空约束),对象具有和同类对象区别唯一的特征
      (字段)。
    2. 外键约束 foreign key
      引用完整性 一个对象需要引用的对象存在来证明正确性。
    3. 检查约束 check
      域完整性 例如:身高在范围的约束内,性别在列表in的约束内,电话在like
      约束内;规则rule
    4. 自定义完整性

    触发器(sqlserver)

    • 满足条件,触发操作
    • DDL触发器
      insert,delete,update;DDL触发器建立在表和视图上,一个表(视图)可以建立多
      个触发器。
    • DDL触发器分为后触发器和替代触发器。
    • 触发器有两张伪表:inserted表和deleted表。
    • create/alter/drop trigger trg_Xxx
    • eg:申请新生入住寝室,需要判断入住的寝室是否已经满员,如果满员拒绝入住。
    基本语法1:
    create trigger trg_admin
    on admin
    for insert
    as
    begin
     print '有插入发生'
    end
    基本语法2:
    alter trigger trg_admin 
    on admin 
    for insert
    as
    begin
     declare @countno int 
     select @countno = count(*) from admin
     if @countno <= 4
     begin 
      print '有插入发生'
     end
     else
     begin
      -- 报错信息 参数1消息,参数2级别,参数3自编号
      raiserror('对不起,已经满员',16,10)
      -- 回滚操作
      rollback transaction
     end
    end
    
    insert into admin values('0005','123','aaa',1)
    解题:
    create trigger trg_changeroom_student 
    on student 
    for insert 
    as 
    begin
        declare @name varchar(20),@newroomno char(4),@countno int,@str varchar(100)
        -- 获取到该学生希望入住的寝室 
        select @name=name,@newroomno = bedno from inserted 
        select @countno = count(*) from student 
        where substring(bedno,1,4) = @newroomno
        -- 判断该学生入住后,寝室是否超员 
        if @countno > 4 
        begin
         set @str='您要入住的寝室'+@newroomno+'已经满员'
         raiserror(@str,16,20)
         rollback transaction
        end
        else 
        begin
          print '欢迎'+@name+'同学入住'+@newroomno+'寝室'
        end
    end
    
    insert  into student(sno,name,sex,high,birthday,jointime,homephone,bedno,address,avgscore,area,cno,imgsrc,pwd) 
    values ('16010102','张三','女',172,'1989-03-01 00:00:00','2009-09-01 00:00:00','13931111112','0301','嘉陵区',73.3,'南充','090101','','123')
    
    select * from studnt
    

    -- 进阶上题
    1.解决插入寝室是否满员
    2.插入的寝室可以入住,编床位号的问题
    3.插入寝室可以入住,找空床

    create trigger trg_changeroom_student
    on student
    for insert,update
    as
    begin
     declare @insertno int,@deleteno int
     declare @name varchar(20),@sno char(8),
      @newroomno char(4),@countno int,@str varchar(100),@oldroomno char(6)
     
     select @insertno = count(*) from inserted
     select @deleteno = count(*) from deleted
     -- 如果插入临时表(幻表)数量 > 0 同时 删除幻表 数量 > 大于0 说明这是修改
    
    
    
    -- 获取到该学生希望入住的寝室
      select @sno=sno,@name=name,@newroomno = bedno from inserted
      select @countno = count(*) from student
      where substring(bedno,1,4) = @newroomno
     -- 判断该学生入住后,寝室是否超员
      if @countno > 4
      begin
           set @str = '您要入住的寝室'+@newroomno + '已经满员'
           raiserror(@str,16,20)
         -- 对于成功入住 插入和修改逻辑一样
         if(@deleteno > 0 and @insertno > 0)
           begin -- 修改的拒绝处理
            select @sno=sno,@name=name,@newroomno = bedno from inserted
            select @oldroomno = bedno from deleted
            print @oldroomno
            update student
            set bedno = @oldroomno
            where sno = @sno 
            print @name + '同学被退回' +@oldroomno + '寝室'
           end
         else -- 插入的拒绝处理
          begin
            rollback transaction
          end
        
         end
     else
      begin
        declare @j int = 1,@temproomno char(4) = @newroomno,@tempbedno char(6)
        while @j <=4   -- 循环产生本寝室合理的床位号,查找该床位是否被使用,
                   --如果没有被使用,退出循环
        begin
         set @tempbedno = @newroomno + '0' + convert(char(1),@j)
         if not exists(select  bedno from student
          where bedno = @tempbedno)
          begin
           print @tempbedno
           update student
           set bedno = @tempbedno
           where sno = @sno
           break
          end
     
        set @j = @j + 1
        end
        print '欢迎' + @name + '同学入住' + @newroomno +'寝室'
      end
    
    end
    
    insert  into student(sno,name,sex,high,birthday,jointime,homephone,bedno,address,avgscore,area,cno,imgsrc,pwd) 
    values ('16010108','张三','女',172,'1989-03-01 00:00:00','2009-09-01 00:00:00','13931111112','0401','嘉陵区',73.3,'南充','090101','','123')
    
    
    delete from student
    where sno = '16010103'
    
    update student
    set bedno = '0301'
    where sno = '16010108'
    
    select * from student
    
    步骤:
    -- 1.通过幻表找出新的寝室
    -- 2.统计新寝室的人数是否超员
    -- 3.如果超员
    
    --    3.1 判断是 插入引发触发,报异常回滚
    --    3.2  修改引入触发 ,报异常 找到原来的寝室号 修改回原寝室(也可以通过回滚取消更新来做,如果不允许直接回床位 
               -- 只能在原寝室重新分配)
    -- 4.不超员 欢迎入住,并计算出床位号
    
    • 找出030101到030104没有人住的床位
    1.创建临时表,查询空床
    create table tempbedno
    (
     tempbedno char(8)
    )
    declare @i int = 1 
    while(@i <= 4) 
    begin
     insert into tempbedno values('0301'+'0'+convert(char(1),i))
     set @i = @i + 1
    end
    
    select * from tempbedno where tempbedno not in(
        select bedno from student 
        where substring(bedno,1,4) = '0301'
    )
    
    drop table tempbedno
    2.循环查询空床
    declare @j int = 1,@temproomno char(6) = '0301',@tempbedno char(6)
    while @j <= 4 
    begin
     set @tempbedno = '0301'+'0'+convert(char(1),@j)
     if not exists(select bedno from student 
     where bedno = @tempbedno)
     begin
      print @tempbedno
      break
     end
     set @j = @j+1
    end
    
    • DCL触发器

    相关文章

      网友评论

          本文标题:09-17:触发器

          本文链接:https://www.haomeiwen.com/subject/eudlnftx.html