SQL圖書館部分功能
一、建表部分
管理員表,讀者表,圖書表,書籍表,借閱表,罰款表
建表前整理好各表主外鍵的關係,數據類型保持一致,最好畫E-R圖的草稿
```c
--------------讀者學生表READERS(卡號,姓名,性別,院系,郵箱,卡狀態)假設學生卡號爲7位,教職工卡號爲5位
--DROP TABLE READERS
--DELETE READERS
--SELECT * FROM READERS
CREATE TABLE READERS (
read_no char(10) primary key,
read_name char(10) not null,
read_sex char(2) ,
read_dept char(10),
Email char(10),
card_status char(10) default '正常'
);
--sex列約束爲男、女
alter table READERS
add constraint sex_check check(read_sex='男' or read_sex='女')
--讀者表插入數據
INSERT INTO readers(read_no,read_name,read_sex,read_dept,Email) values('read001','一號選手','男','計算機系','email001');
GO
---------------管理員表(工號,姓名,聯繫方式)
--drop adm
--SELECT * FROM ADM
CREATE TABLE ADM(
adm_no char(10) primary key,
adm_name char(10) ,
adm_number char(10)
);
--插入數據
INSERT INTO ADM VALUES ('adm001','管理員一號','number001');
GO
----------------圖書類別表catalog(ISBN,cata_name,cata_price,cata_writer,cata_publish,cata_total)
--DROP TABLE CATALOG
--SELECT * FROM CATALOG
CREATE TABLE CATALOG
(
ISBN char(13) primary key,
cata_name char(10) ,
cata_price decimal(10,2),
cata_writer char(10),
cata_publish char(10),
cata_total int default 0,
adm_no char(10),
foreign key (adm_no) references ADM(adm_no)
)
GO;
-----------------圖書表(圖書ID,圖書名稱,狀態,管理員工號)
--SELECT * FROM BOOKS
--DROP TABLE BOOKS
--ALTER TABLE BOOKS
--ADD book_name char(10)
CREATE TABLE BOOKS(
book_no char(20) primary key,
ISBN char(13),
book_name char(10),
book_status char(10) default'可借',
foreign key(ISBN) references CATALOG(ISBN)
);
--圖書表中插入數據
--INSERT INTO BOOKS(book_no,ISBN,adm_no,book_name) values('book001','isbn001','adm001','天生有罪');
GO
-----------------FINE(借書證號,圖書編號,罰款金額)
--SELECT * FROM FINE
CREATE TABLE FINE(
read_no char(10),
book_no char(20),
obey_money float,
constraint pk_fine primary key(read_no,book_no),
foreign key (read_no) references READERS(read_no),
foreign key (book_no) references BOOKS(book_no),
);
GO
-----------------借閱表(卡號,圖書號,借書時間,應還時間,還書時間,續借狀態)
--SELECT * FROM BORROW
--select * from books
--drop table borrow
CREATE TABLE BORROW(
read_no char(10),
book_no char(20),
borr_time date default convert(date,getdate()),
due_time date default convert(date,dateadd(month,1,getdate())),
return_time date,
renew_status char(10) default '未續借',
CONSTRAINT pk_borr PRIMARY KEY (read_no,book_no),
foreign key (read_no) references READERS(read_no),
foreign key (book_no) references BOOKS(book_no)
);
GO
二、圖書錄入功能
思路:
- 爲catalog創建存儲過程,輸入ISBN,書名,價格,作者,出版社,冊數,管理員工號
- 爲catalog創建觸發器,當向catalog插入數據時,自動向Books表中插入記錄
(1) Books中記錄條數與冊數相同,用while(@i<冊數)循環實現;
(2) 圖書號book_no=concat(book,ISBN,@i)自動生成,ISBN,book_name從inserted表中獲取,book_status默認爲
可借。
---------------------------------------------------------------------錄入功能-------------------------------------------------------------------------------------
---------------------------------------------------------------------INSERT CATALOG,BOOKS表自動插入BOOKS信息----------------------------------------------
GO;
---------Pro_InsertCatalog,圖書管理員錄入圖書信息
CREATE PROCEDURE Pro_InsertCatalog
@ISBN char(13),
@cata_name char(10),
@cata_price decimal(10,2),
@cata_writer char(10),
@cata_publish char(10),
@cata_total int,
@adm_no char(10)
AS
BEGIN
INSERT INTO CATALOG VALUES(@ISBN,@cata_name,@cata_price,@cata_writer,@cata_publish,@cata_total,@adm_no);
END
GO;
----------Tri_InsertCatalog,向catalog插入信息時,自動向BOOKS表插入信息
--圖書表(圖書ID,圖書名稱,狀態,管理員工號)
CREATE TRIGGER Tri_InsertCatalog ON CATALOG FOR INSERT AS
BEGIN
-----當catalog中插入圖書冊數爲n時,BOOKS表需插入n條記錄
DECLARE @cata_total int SET @cata_total=(SELECT cata_total FROM INSERTED)
DECLARE @ISBN char(13) SET @ISBN=(SELECT ISBN FROM INSERTED)
DECLARE @cata_name char(10) SET @cata_name=(SELECT cata_name FROM INSERTED)
DECLARE @i INT SET @i=1 --循環變量
WHILE(@i<=@cata_total)
BEGIN
--自動生成BOOKS的book_no=book+ISBN+@i
declare @book_no char(20) set @book_no=concat('book',@ISBN,convert(char(3),@i))
INSERT INTO BOOKS(book_no,ISBN,book_name) VALUES(@book_no,@ISBN,@cata_name)
set @i=@i+1
END
END
GO;
-----------測試圖書錄入功能
delete books
delete catalog
select * from catalog go;
select * from books;
exec Pro_InsertCatalog 'isbn123456001','圖書一號',48.50,'作者一號','出版社一號',5,'adm001'
三、借書功能
思路:
1.存儲過程pro_insertBorrow,輸入讀者卡號、圖書編號,自動將該記錄插入到borrow表
(1)借閱時間取當前系統時間getdate(),
(2)應還時間爲dateadd(month,1,getdate()),(3)續借狀態默認爲未續借
2 觸發器Tri_insertBorrow
(1) 從inserted表中提取信息,賦值給@read_no,@book_no
(2) 檢查read_no對應的讀者卡號是否掛失,掛失則rollback,不允許借書(3) 檢查book_no對應的書籍是否可借閱,已被借閱則rollback,不允許借書
(4) 卡號正常,書可借時,更新books表中書編號@book_no的狀態爲不可借
------------------------------------------------------借閱功能,insert borrow時--------------------------------------
------------------------------------------------------將書狀態改爲不可借-----------------------------------------------
-------------------存儲過程pro_InsertBorrow,輸入read_no,ISBN,向BORROW中插入借閱記錄
--DROP PROCEDURE pro_InsertBorrow
CREATE PROCEDURE pro_InsertBorrow @ReadNo char(10),@BookNo char(20) AS
BEGIN
INSERT INTO BORROW(read_no,book_no) VALUES(@ReadNo,@BookNo)
END
--------------------觸發器Tri_InsertBorrow,向Borrow中插入借閱記錄時,自動改變書的狀態
GO
--drop trigger Tri_InsertBorrow
CREATE TRIGGER Tri_InsertBorrow ON BORROW FOR INSERT AS
BEGIN
------從insert 表中收集信息
declare @read_no char(10) set @read_no =(select read_no from inserted)
declare @book_no char(20) set @book_no =(select book_no from inserted)
print (@read_no)
print(@book_no)
--讀者卡掛失
IF((select card_status from READERS where read_no =@read_no)='掛失')
BEGIN
rollback
print'此卡已掛失,不可借書'
END
--書已被借走,不可借閱
IF((select book_status from BOOKS where book_no =@book_no)='不可借' )
BEGIN
rollback
print '此書已被接走,不可借閱'
END
IF((select card_status from READERS where read_no =@read_no)='正常'
AND (select book_status from BOOKS where book_no =@book_no)='可借')
BEGIN
print'借書成功'
--更改BOOKS表中的book_status
UPDATE BOOKS
SET book_status='不可借'
WHERE book_no =@book_no
END
END
go;
-------------------------------------------測試借書功能Pro_InsertBorrow,Tri_InsertBorrow
select * from BOOKS;
select * from READERS;
select * from BORROW;
--delete borrow
UPDATE READERS SET card_status='正常' WHERE read_no='read001'
UPDATE BOOKS SET book_status='可借' WHERE book_no='bookisbn1234560011'
exec pro_InsertBorrow 'read001','bookisbn1234560011'
go;
四、還書功能
思路:
1 存儲過程Pro_updateBorrowReturn,輸入book_no,read_no,retur_time,更新borrow表中的還書時間
2 觸發器Tri_updateBorrowReturn
(1) 從inserted表中提取信息,賦值給@read_no,@book_no,@return_time,@due_tiem;
(2)比較@due_tme,@return_time,datediff(day,@due_time,@return_time)>0則 超期,將讀者 卡號,圖書編號,罰款金額(超期天數*0.1)插入罰款表
(3)更新books表中圖書編號爲@book_no書籍的book_stutus爲可借
------------------------------------------存儲過程還書Pro_UpdateBorrowReturn,輸入還書日期,更新歸還時間
CREATE PROCEDURE Pro_UpdateBorrowReturn
@ReadNO char(10),
@BookNo char(20),
@ReturnTime date AS
BEGIN
UPDATE BORROW
SET return_time=@ReturnTime
WHERE read_no = @ReadNO AND book_no = @BookNo
END
go;
-----------------------觸發器Tri_UpdateBorrowReturn 更新BORROW return_time時,將書改爲可借,超期生成罰款單
--DROP TRIGGER Tri_UpdateBorrowReturn
CREATE TRIGGER Tri_UpdateBorrowReturn ON BORROW FOR UPDATE AS
BEGIN
declare @ReadNo char(10) set @ReadNo =(select read_no from inserted)
declare @BookNo char(20) set @BookNo=(select book_no from inserted)
declare @ReturnTime date set @ReturnTime=(select return_time from inserted)
declare @DueTime date set @DueTime=(select due_time from inserted)
--列級觸發器
IF UPDATE(return_time)
BEGIN
--將書改爲可借
UPDATE BOOKS SET book_status ='可借' WHERE book_no=@BookNo
--判斷是否超期
IF (datediff(day,@DueTime,@ReturnTime)>0)
BEGIN
print '借書超期,超期一天罰款0.1元'
declare @dalay_day int set @dalay_day=abs(datediff(day,@DueTime,@ReturnTime))
declare @money float set @money=0.1*@dalay_day
INSERT INTO FINE VALUES (@ReadNo,@BookNo,@money);
END
END
END
go;
------------------------------------------------------測試還書功能,還書更新return_time,超期生成罰款單
select * from BOOKS;
select * from READERS;
select * from BORROW;
select * from FINE;
--delete borrow
--借書部分
UPDATE READERS SET card_status='正常' WHERE read_no='read001'
UPDATE BOOKS SET book_status='可借' WHERE book_no='bookisbn123456001'
exec pro_InsertBorrow 'read001','bookisbn1234560011'
--還書部分
exec Pro_UpdateBorrowReturn 'read001','bookisbn1234560011','2020-05-29'
go;
五、續借功能
思路:
總結:圖書的是否被借閱過要從deleted的舊錶中查看,inserted表肯定是顯示爲續借的。
1 存儲過程Pro_updateBorrowDue 輸入讀者卡號,圖書編號,實現book_status更新
2 觸發器Tri__updateBorrowDue
(1) 從deleted表收集圖書原來的book_status,read_no,book_no
(2) 如果book_status顯示爲已續借,則該讀者已續借過一次,不可再次續借.
(3) 檢查read_no字段的長度,如果爲7位長,則爲學生,可續借1個月,更新books表的due_time=dateadd(month,1,@due_time)
(4) 檢查read_no字段的長度,如果爲6位長,則爲學生,可續借3個月,更新books表的due_time=dateadd(month,3,@due_time)
----------------------------------------------------續借存儲過程Pro_UpdateBorrowDue,教職工卡考位8位,可續借三個月,學生卡號爲10位,可續借一個月
--DROP PROCEDURE Pro_UpdateBorrowDue
CREATE PROCEDURE Pro_UpdateBorrowDue
@ReadNo char(10),
@BookNo char(20) AS
BEGIN
UPDATE BORROW SET renew_status = '已續借' WHERE read_no = @ReadNo AND book_no = @BookNo
END
GO;
---------------------------------------------------觸發器續借Tri_UpdateBorrowDue,已續借不可續借,卡號7位可續借1個月,卡號6位可續借3個月
--DROP TRIGGER Tri_UpdateBorrowDue
CREATE TRIGGER Tri_UpdateBorrowDue ON BORROW FOR UPDATE AS
BEGIN
declare @ReadNo char(10) set @ReadNo=(select read_no from inserted)
declare @BookNo char(20) set @BookNo=(select book_no from inserted)
declare @RenewStatus char(10) set @RenewStatus=(select renew_status from deleted) -------------查看deleted表中續借狀態
declare @DueTime date set @DueTime=(select due_time from inserted)
IF UPDATE(renew_status)
BEGIN
-----判斷是否已續借
IF(@RenewStatus='已續借')
BEGIN
rollback
print'此書已續借,不可再次續借'
END
IF(@RenewStatus='未續借')
BEGIN
print'此書未續借,可續借'
-----判斷是教師還是學生
print(len(@ReadNO))
IF(LEN(@ReadNo)=7)-----學生
BEGIN
---更新due_tim,renew_status
UPDATE BORROW SET due_time=CONVERT(date,dateadd(month,1,@DueTime) ) WHERE book_no =@BookNo AND read_no =@ReadNo
UPDATE BORROW SET renew_status='已續借' WHERE book_no =@BookNo AND read_no =@ReadNo
print'續借成功,已延期一個月'
END
IF(LEN(@ReadNo)=6)-----教師
BEGIN
---更新due_time, renew_status
UPDATE BORROW SET due_time=CONVERT(date,dateadd(month,3,@DueTime) ) where book_no =@BookNo AND read_no =@ReadNo
UPDATE BORROW SET renew_status='已續借' WHERE book_no =@BookNo AND read_no =@ReadNo
print'續借成功,已延期三個月'
END
END
END
END
GO;
---------------------------------------------------測試續借功能
select * from BOOKS;
select * from READERS;
select * from BORROW;
select * from FINE;
--delete borrow
--delete fine
--借書部分
UPDATE READERS SET card_status='正常' WHERE read_no='read001'
UPDATE BOOKS SET book_status='可借' WHERE book_no='bookisbn1234560011'
exec pro_InsertBorrow 'read001','bookisbn1234560011'
--續借部分
exec Pro_UpdateBorrowDue 'read001' ,'bookisbn1234560011'
-------------------------------------------教師借書
--借書部分
INSERT INTO READERS(read_no,read_name,read_sex,read_dept,Email) VALUES('Tea001','教師一號','男','計算機系','Email002')
UPDATE READERS SET card_status='正常' WHERE read_no='Tea001'
UPDATE BOOKS SET book_status='可借' WHERE book_no='bookisbn1234560012'
exec pro_InsertBorrow 'Tea001','bookisbn1234560012'
--續借部分
exec Pro_UpdateBorrowDue 'Tea001' ,'bookisbn1234560012'
GO;
六、查看一個學生的借閱的圖書
存儲過程 Pro_checkReaderBooks
(1) 輸入讀者卡號,返回讀者借閱的圖書名稱和圖書編號
(2) 將borrow和reader表自然連接,即讀者卡號相同的連接,將卡號爲輸入卡號的元組篩選出來,投影出圖書編號和圖書名稱兩列
(3) SQL:select book_name,book_no
From reader inner jion borrow on reader.read_no =borrow.book_no
Where read_no = @Read_no
----------------------------------------------------------------查詢某讀者借閱的所有圖書------------------------------------------------------------------------------------
-----------------------------------------------------------------Pro_checkReaderBooks
CREATE PROCEDURE Pro_checkReaderBooks
@read_no char(10),
@book_no char(20) output,
@book_name char(10) output
AS
BEGIN
set @book_no=
(SELECT borrow.book_no
FROM BORROW,BOOKS
WHERE borrow.book_no=books.book_no
AND read_no =@read_no)
set @book_name=
(SELECT books.book_name
FROM BORROW,BOOKS
WHERE borrow.book_no=books.book_no
AND read_no =@read_no)
END
go;
---------------測試
declare @BookNo char(20)
declare @BookName char(10)
exec Pro_checkReaderBooks 'read001', @BookNo output, @BookName output
print @BookNo
print @BookName
七、總結
1.連接字符串可以用concat(),以此自動生成book_no=concat(‘book’+’isbn’+@i)
當設值的大小大於isbn實際的大小時,concat連接會有空格
2 identity(初始值,步長)只能用於建表或修改表時的某一列,不能用於和isbn+identity(1,1)生成book_no
3.聚合函數的使用
select 的列名必須在group by 【列1】 中,因爲group之後,【列1】值相同的記錄歸納爲一組了。