SQL觸發器綜合習題
總結
1 每寫完一段代碼時,後面加一個go,方便後面的分段執行
2 在創建表的代碼前備註好 select * from 表名,delete 、drop 以便調試,創建觸發器前也備註好刪除觸發器的SQL代碼,觸發器創建完成後,要寫go
3 最好不要在建表後,馬上插入數據,而是在測試觸發器時,再給出相應的代碼,測試完一個功能後,刪除數據。
保證每一次測試的環境都是我們現場給出的。
4 where 子句中某一列中的值寫錯了,不會報錯
5 if 語句中同時滿足兩個條件用and 滿足二者之一 用or
建表、插入數據、建立觸發器、測試觸發器
--讀者表(卡號,姓名,性別,院系,郵箱,卡狀態)
--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)
);
--sex列約束爲男、女
alter table READERS
add constraint sex_check check(read_sex='男' or read_sex='女')
--讀者表插入數據
INSERT INTO readers 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
--創建圖書表(圖書ID,圖書名稱,狀態)
--SELECT * FROM BOOKS
--DROP TABLE BOOKS
CREATE TABLE BOOKS(
book_no char(10) primary key,
ISBN char(10) not null,
b_status char(10),
adm_no char(10),
foreign key (adm_no) references ADM(adm_no)
);
--圖書表中插入數據
INSERT INTO BOOKS values('book001','isbn001','可借','adm001');
GO
--FINE(借書證號,圖書編號,罰款金額)
CREATE TABLE FINE(
read_no char(10),
book_no char(10),
obey_money float,
constraint pk_fine primary key(read_no,book_no)
);
GO
--創建借閱表(卡號,圖書號,借書時間,應還時間,還書時間,續借狀態)
--SELECT * FROM BORROW
--select * from books
--drop table borrow
CREATE TABLE BORROW(
read_no char(10),
book_no char(10),
borr_time char(20) default convert(char(20),getdate()),
due_time char(20) default convert(char(20),dateadd(month,1,getdate())),
return_time char(20) default 'null',--默認空值怎麼寫
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)
);
--備份borrow表
--SELECT * FROM BORR_BAK
SELECT * INTO BORR_BAK FROM BORROW
--刪除borrow表中的所有記錄
DELETE BORROW
---------------------------------------------觸發器Tri_InsertBorrow-----------------------------------
go
--創建觸發器 Tri_InsertBorrow
--(1)檢查借閱證號,掛失則顯示‘借書證已掛失’rollback
--(2)檢查圖書是否可解,不可借則顯示‘圖書不可借閱’rollback
--(3)兩者都不滿足,則可以插入借閱表,更新books表中的借閱狀態
--DROP TRIGGER Tri_InsertBorrow
CREATE TRIGGER Tri_InsertBorrow ON BORROW FOR INSERT AS
BEGIN
IF (select card_status
from inserted as I inner join readers as R
on I.read_no = R.read_no)='掛失'
BEGIN
print '該借書證已掛失,不可借書'
rollback
END
IF (select b_status
from inserted as I inner join books as B
on I.book_no = B.book_no)='不可借'
BEGIN
print '圖書已被借,不可借閱'
rollback
END
IF (select card_status
from inserted as I inner join readers as R
on I.read_no = R.read_no)='正常'
AND (select b_status
from inserted as I inner join books as B
on I.book_no = B.book_no)= '可借'
BEGIN
print '借書成功'
UPDATE BOOKS
set b_status='不可借'
from books as B inner join inserted as I
on B.book_no=I.book_no
END
END
go
--測試Tri_InsertBorrow
--DELETE BORROW
--SELECT * FROM BORROW
--SELECT * FROM BOOKS
--SELECT * FROM READERS
--TEXT1 卡號正常,圖書可借
update readers
set card_status='正常'
where read_no ='read001'
update books
set b_status = '可借'
where book_no='book001'
INSERT INTO BORROW(read_no,book_no) VALUES('read001','book001');
delete borrow
--TEXT2 卡號正常,圖書不可借
update readers
set card_status='正常'
where read_no ='read001'
update books
set b_status = '不可借'
where book_no='book001'
INSERT INTO BORROW(read_no,book_no) VALUES('read001','book001');
delete BORROW
--TEXT3 卡號掛失,圖書可借
update readers
set card_status='掛失'
where read_no ='read001'
select * from readers
update books
set b_status = '可借'
where book_no='book001'
INSERT INTO BORROW(read_no,book_no) VALUES('read001','book001');
delete borrow
--創建觸發器Tri_UpdateBorrow
--修改borrow(return_time)時,將books(b_status)改爲可借
--判斷是否超期 datediff(day,getdate(),convert(datetime,due_time))>0
--超期將read_no ,book_no,money追加到罰款單fine表中。
--疑惑:將return_time 設置爲datetime數據類型,怎麼設置爲空呢?不給值就好!
go
---------------------------觸發器Tri_UpdateBorrow-----------------------------------------------------
--drop TRIGGER Tri_UpdateBorrow
CREATE TRIGGER Tri_UpdateBorrow ON BORROW FOR UPDATE AS
BEGIN
--將books改爲可借
IF UPDATE(return_time)
BEGIN
UPDATE BOOKS
set b_status='可借'
from books as B inner join inserted as I
on B.book_no = I.book_no
END
--處理超期
declare @dueTime date --存放應還書時間,borrow中就有應還時間
set @dueTime=convert(date,(select due_time from inserted ))
declare @returnTime date --存放還書時間 ,borrow表 即inserted表
set @returnTime=(select return_time from inserted)
declare @delay_day int --存放超期時間
set @delay_day = datediff(day,@returnTime,@dueTime)
print @delay_day
IF @delay_day<0
BEGIN
print '@delay_day'
--將讀者卡號,書籍編號,罰款金額寫入fine表,設超期一天,罰款金額爲0.1
declare @readNo char(10) set @readNo=( select read_no from inserted)
declare @bookNo char(10) set @bookNo=( select book_no from inserted)
INSERT INTO FINE values (@readNo,@bookNo,abs(@delay_day*0.1));
print '已插入罰款單'
END
END
go
--測試 Tri_updateBorrow
--select * from borrow
--select * from books
--select * from fine
--刪除掉原有數據,重新插入,方便測試
delete fine
delete borrow
delete books
INSERT INTO BOOKS values('book001','isbn001','可借','adm001');
INSERT INTO BORROW(read_no,book_no) VALUES('read001','book001');--觸發 Tri_insertBorrow,b_status變爲不可借
--text1
update borrow
set return_time='2020-6-9'
where read_no='read001'
AND book_no = 'book001'
--如books表book001書籍狀態改爲可借
--在fine表中有read001的罰款記錄 ,則測試成功