zoukankan      html  css  js  c++  java
  • SQL Server 中的存储过程和触发器实例

    针对简易图书管理数据库 BooksDB,完成下述功能。

    1、不带参数的存储过程:创建一个存储过程,查看所有读者的姓名、可借本数、可借天数和已借 书本数。

    2、带输入参数的存储过程:创建一个存储过程,实现借书功能;

    3、带输入参数的存储过程:创建一个存储过程,实现还书功能;

    4、带输入参数和输出参数的存储过程:创建一个存储过程,输入读者的编号,输出该读者的姓名;

    5、创建 DDL 触发器,禁止用户修改 BooksDB 数据库中的表;

    6、测试 AFTER 触发器,理解 INSERTED 表和 DELETED 表的作用;

    BooksDB中的几个表:

    1、不带参数的存储过程:

    创建一个存储过程,查看所有读者的姓名、可借本数、可借天数和已借书本数。

    create procedure usp_GetInfo 
    as 
        select rdName, canLendQty, canLendDay, rdBorrowQty from Reader, ReaderType
        where Reader.rdType = ReaderType.rdType
    调用的时候:
    exec usp_GetInfo

    2、带输入参数的存储过程:

    创建一个存储过程,实现借书功能;

    create procedure usp_BorrowBook
    
        @rdID char(9),
    
        @bkID char(9)
    
    as
    
        --先判断有没有这本书
    
        if not exists(select * from Book where @bkID in (select bkID from Book))
    
        begin
    
               raiserror('图书馆没有该书,借阅失败',10,1)
    
               return
    
        end
    
        --先判断书是否在馆
    
        declare @bkState int
    
        select @bkState = bkState from Book
    
        where bkID = @bkID
    
        if @bkState = 0
    
        begin
    
               raiserror('该书不在馆,无法借阅',10,1)
    
               return
    
        end
    
        --在判断该读者的借书数量是否达到最大借书数量
    
        declare @rdBorrowQty int , @canLendQty int
    
        select @rdBorrowQty = rdBorrowQty from Reader
    
        where rdID = @rdID
    
        select @canLendQty =  canLendQty from ReaderType
    
        where rdType = (select rdType from Reader where rdID = @rdID)
    
        if @rdBorrowQty = @canLendQty
    
        begin
    
               raiserror('抱歉!你所借书的数量已经达到最大借书数量!借阅失败!',10,1)
    
               return
    
        end
    
        --借书开始(1.修改书的状态,2.修改改读者的借书数量,3.向Borrow表中插入数据)
    
        update Book
    
        set bkState = 0
    
        where bkID = @bkID
    
     
    
        update Reader
    
        set rdBorrowQty = rdBorrowQty + 1
    
        where rdID = @rdID
    
     
    
        declare @canLendDay int
    
        select @canLendDay = canLendDay from ReaderType
    
        where rdType = (select rdType from Reader where rdID = @rdID)
    
        insert into Borrow values(@rdID,@bkID,GETDATE(),DATEADD(dd,@canLendDay,GETDATE()),null)
    
    --调用:
    
    exec usp_BorrowBook 'rd2017001','bk2017006'

     

    exec usp_BorrowBook 'rd2017001','bk2017002'
    
    exec usp_BorrowBook 'rd2017002','bk2017002'
    
    --由于bk2017002已经被借出去了,所以会出现不在馆的消息

     

    3、带输入参数的存储过程:

    创建一个存储过程,实现还书功能;

     1 create procedure usp_ReturnBook
     2 
     3        @rdID char(9),
     4 
     5        @bkID char(9)
     6 
     7 as
     8 
     9        --还书(1.修改书的状态,2.修改读者的借书数量,3.在Borrow表中删除这条借书纪录)
    10 
    11        update Book set bkState = 1
    12 
    13        where bkID = @bkID
    14 
    15  
    16 
    17        update Reader set rdBorrowQty = rdBorrowQty - 1
    18 
    19        where rdType = (select rdType from Reader where rdID = @rdID)
    20 
    21  
    22 
    23        delete from Borrow
    24 
    25        where rdID = @rdID and bkID = @bkID
    26 
    27 --调用
    28 
    29 exec usp_ReturnBook 'rd2017001','bk2017002'

    4、带输入参数和输出参数的存储过程:

    创建一个存储过程,输入读者的编号,输出该读者的姓名;

     1 create procedure usp_GetName
     2 
     3     @rdID char(9),
     4 
     5     @rdName varchar(20) output
     6 
     7 as
     8 
     9     select @rdName = rdName from Reader
    10 
    11     where rdID = @rdID
    12 
    13 go
    14 
    15 --调用
    16 
    17 declare @rdName varchar(20)
    18 
    19 exec usp_GetName 'rd2017001',@rdName output
    20 
    21 select @rdName 姓名

     

    5、创建 DDL 触发器:

    禁止用户修改 BooksDB 数据库中的表;、

    create trigger tri_OnBookDB on database
    
    for ddl_table_events
    
    as
    
        print '无法在数据库BookDB中创建,删除,修改表!!'
    
        rollback
    
    --测试:
    
    create table Test (a int,b char(6))
    
    drop table Borrow

     

    6、测试 AFTER 触发器,理解 INSERTED 表和 DELETED 表的作用;

     Instead of触发器:

    一开始Borrow表中有这样一条纪录:

       

    当创建Instead of 触发器后:

    create trigger tri_InsteadOf on Borrow instead of delete
    
    as
    
        select rdID, bkID from deleted
    
    --调用:
    
    delete from Borrow where rdID = 'rd2017001'

    deleted表中会出现:

     

    但是在Borrow表中这条纪录并没有被删除。原因是触发器中代替了所要执行的delete操作。

    After 触发器:

    当向Borrow表中插入一条纪录时候,应修改Reader表中的rdBorrowQty加1,而在Book表中修改相应的书的状态为0。

     1 alter trigger tri_Insert on Borrow after insert
     2 
     3 as
     4 
     5     --先要判断该书在不在馆
     6 
     7     if not exists(select bkState from Book, inserted where Book.bkID = inserted.bkID)
     8 
     9     begin
    10 
    11         raiserror('该书不在馆,无法插入!',10,1)
    12 
    13         return
    14 
    15     end
    16 
    17  
    18 
    19     update Reader set rdBorrowQty = rdBorrowQty + 1
    20 
    21     from Reader, inserted
    22 
    23     where Reader.rdID = inserted.rdID
    24 
    25  
    26 
    27     update Book set bkState = 0
    28 
    29     from Book, inserted
    30 
    31     where Book.bkID = inserted.bkID
    32 
    33  
    34 
    35 --调用:
    36 
    37 insert into Borrow values ('rd2017004','bk2017004',GETDATE(),30,null)

    学习过程之中难免存在错误,望多多指出。

  • 相关阅读:
    CentOS6.8下安装Docker
    xshell连接Linux(centos6.8)失败的解决方法
    Windows Server定时执行bat
    [译]看漫画学Flux
    LeetCode题型分类及索引
    LeetCode & Q38-Count and Say-Easy
    LeetCode & Q20-Valid Parentheses-Easy
    LeetCode & Q14-Longest Common Prefix-Easy
    LeetCode & Q13-Roman to Integer-Easy
    LeetCode & Q28-Implement strStr-Easy
  • 原文地址:https://www.cnblogs.com/yangfan-123/p/6773824.html
Copyright © 2011-2022 走看看