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的罚款记录 ,则测试成功