A.在修课表的考试日期列上定义一个CHECK约束 B.在修课表上建立一个插入和更新操作的触发器 C.在学生表上建立一个插入和更新操作的触发器 D.在修课表的考试日期列上定义一个外码引用约束
·37· 9.设有教师表(教师号,教师名,职称,基本工资),其中基本工资的取值范围与教师职称有关,比如,教授的基本工资是6000~10000,副教授的基本工资是4000~8000。下列实现该约束的方法中,可行的是 C
A. 可通过在教师表上定义插入和修改操作的触发器实现 B. 可通过在基本工资列上定义一个CHECK约束实现 C. A和B都可以 D. A和B都不可以
10.设在SC(Sno,Cno,Grade)表上定义了触发器:
CREATE TRIGGER tri1 ON SC INSTEAD OF INSERT … 当执行语句:INSERT INTO SC VALUES('s001', 'c01',90)
会引发该触发器执行。下列关于触发器执行时表中数据的说法,正确的是 D A.SC表和INERTED表中均包含新插入的数据 B.SC表和INERTED表中均不包含新插入的数据
C.SC表中包含新插入的数据,INERTED表中不包含新插入的数据 D.SC表中不包含新插入的数据,INERTED表中包含新插入的数据 11.设在SC(Sno,Cno,Grade)表上定义了触发器:
CREATE TRIGGER tri1 ON SC AFTER INSERT … 当执行语句:INSERT INTO SC VALUES('s001', 'c01',90)
会引发该触发器执行。下列关于触发器执行时表中数据的说法,正确的是 A A.SC表和INERTED表中均包含新插入的数据 B.SC表和INERTED表中均不包含新插入的数据
C.SC表中包含新插入的数据,INERTED表中不包含新插入的数据 D.SC表中不包含新插入的数据,INERTED表中包含新插入的数据
12.当执行由UPDATE语句引发的触发器时,下列关于该触发器临时工作表的说法,正确的是 C
A.系统会自动产生UPDATED表来存放更改前的数据 B.系统会自动产生UPDATED表来存放更改后的数据
C.系统会自动产生INSERTED表和DELETED表,用INSERTED表存放更改后的数据,用DELETED表存放更改前的数据
D.系统会自动产生INSERTED表和DELETED表,用INSERTED表存放更改前的数据,用DELETED表存放更改后的数据
13.下列关于游标的说法,错误的是 D
A.游标允许用户定位到结果集中的某行 B.游标允许用户读取结果集中当前行位置的数据 C.游标允许用户修改结果集中当前行位置的数据
D.游标中有个当前行指针,该指针只能在结果集中单向移动
14.对游标的操作一般包括声明、打开、处理、关闭、释放几个步骤,下列关于关闭游标的说法,错误的是
A.游标被关闭之后,还可以通过OPEN语句再次打开 B.游标一旦被关闭,其所占用的资源即被释放 C.游标被关闭之后,其所占用的资源没有被释放
37
B
·38· D.关闭游标之后的下一个操作可以是释放游标,也可以是再次打开该游标
二. 填空题
1.利用存储过程机制,可以_____数据操作效率。 提高
2.存储过程可以接受输入参数和输出参数,对于输出参数,必须用_____词来标明。 OUTPUT 3.执行存储过程的SQL语句是_____。 EXEC (EXECUTE)
4.调用存储过程时,其参数传递方式有_____和_____两种。按参数位置 按参数名 5.修改存储过程的SQL语句是_____。ALTER PROC
6.SQL Server支持两种类型的触发器,它们是_____触发型触发器和_____触发型触发器。 前 后 7.在一个表上针对每个操作,可以定义_____个前触发型触发器。 一
8.如果在某个表的INSERT操作上定义了触发器,则当执行INSERT语句时,系统产生的临时工作表是_____。 INSERTED
9.对于后触发型触发器,当触发器执行时,引发触发器的操作语句(已执行完/未执行)_____。 已执行完 10.对于后触发型触发器,当在触发器中发现引发触发器执行的操作违反了约束时,需要通过_____语句撤销已执行的操作。 ROLLBACK
11.打开游标的语句是_____。 OPEN cursor_name
12.在操作游标时,判断数据提取状态的全局变量_____。 @@fetch_status 四.上机练习
以下各题均利用第3、4章建立的Students数据库以及Student、Course和SC表实现。 1. 创建满足下述要求的存储过程,并查看存储过程的执行结果。 (1) 查询每个学生的修课总学分,要求列出学生学号及总学分。
create proc p1 as
select sno,SUM(credit) as 总学分
from SC join Course c on c.Cno=SC.Cno group by sno
(2) 查询学生的学号、姓名、修的课程号、课程名、课程学分,将学生所在系作为输入参数,默认值为“计算机
系”。执行此存储过程,并分别指定一些不同的输入参数值,查看执行结果。 create proc p2
@dept varchar(20) = '计算机系' as
select s.sno,sname,c.cno,cname,credit from Student s join SC on s.Sno=SC.Sno join Course c on c.Cno=SC.Cno
where Sdept = @dept 执行示例1:EXEC P2
执行示例2:EXEC P2 '通信工程系'
(3) 查询指定系的男生人数,其中系为输入参数,人数为输出参数。
create proc p3
@dept varchar(20),@rs int output as
select @rs = COUNT(*) from Student where Sdept = @dept and Ssex = '男'
38
(4) 删除指定学生的修课记录,其中学号为输入参数。
create proc p4 @sno char(7) as
delete from SC where Sno = @sno
(5) 修改指定课程的开课学期。输入参数为:课程号和修改后的开课学期。
create proc p5
@cno char(6),@x tinyint as
update Course set Semester = @x where Cno = @cno
2. 创建满足下述要求的触发器(前触发器、后触发器均可),并验证触发器执行情况。 (1) 限制学生的年龄在15~45之间。
create trigger tri1
on student after insert,update as
if exists(select * from inserted where sage not between 15 and 45) rollback
(2) 限制学生所在系的取值范围为{计算机系,信息管理系,数学系,通信工程系}
create trigger tri2
on student after insert,update as
if exists(select * from student where sdept not in ('计算机系','信息管理系','数学系','通信工程系'))
Rollback
(3) 限制每个学期开设的课程总学分在20~30范围内。
create trigger tri3
on course after insert,update as
if exists(select sum(credit) from course
where semester in (select semester from inserted ) having sum(credit) not between 20 and 30 ) Rollback
(4) 限制每个学生每学期选课门数不能超过6门(设只针对插入操作)。
create trigger tri4 on sc after insert as
if exists(select * from sc join course c on sc.cno = c.cno where sno in (select sno from inserted) group by sno,semester
39
·39· ·40· having count(*) > 6 ) rollback
3. 创建满足下述要求的游标,并查看游标的执行结果。
(1) 列出VB考试成绩最高的前2名和最后1名学生的学号、姓名、所在系和VB成绩。
declare @sno char(10),@sname char(10),@dept char(14),@grade char(4) declare c1 SCROLL cursor for select s.sno,sname,sdept,grade
from student s join sc on s.sno = sc.sno join course c on c.cno = sc.cno where cname = 'vb' order by grade desc open c1
print ' 学号 姓名 所在系 VB成绩'
print '---------------------------------------' fetch next from c1 into @sno ,@sname ,@dept ,@grade if @@FETCH_STATUS = 0
print @sno + @sname + @dept + @grade
fetch next from c1 into @sno ,@sname ,@dept ,@grade if @@FETCH_STATUS = 0
print @sno + @sname + @dept + @grade
fetch last from c1 into @sno ,@sname ,@dept ,@grade if @@FETCH_STATUS = 0
print @sno + @sname + @dept + @grade close c1 deallocate c1
(2) 列出每个系年龄最大的名学生的姓名和年龄,将结果按年龄降序排序。
declare @sname char(10),@age char(4),@dept char(20) declare c1 cursor for select distinct sdept from student open c1
fetch next from c1 into @dept while @@FETCH_STATUS = 0 begin
print @dept
declare c2 cursor for
select top 2 with ties sname,sage from student where sdept = @dept order by sage desc open c2
fetch next from c2 into @sname ,@age if @@FETCH_STATUS = 0 print @sname + @age fetch next from c2 into @sname ,@age if @@FETCH_STATUS = 0 print @sname + @age print '' close c2 deallocate c2
fetch next from c1 into @dept
40