本文提供了4道典型的题目
题目 + 答案 + 分析
-- 前排提示:下题中使用的表极其主键为 studentInfo(stuId), subjectInfo(subId), scoreInfo(stuId, subId)
-- Q1:该存储过程有两个输入参数(@specialty, @name),查询某系,某姓名的学生信息:包括学号、姓名、年龄、课程名、成绩
-- 注:要求在创建存储过程之前,判断该存储过程是否已创建,若已创建则先删除,并给出"已删除";否则给出"不存在,可创建"
-- 判断存储过程是否已经存在:
if exists(select name from sysobjects where name = 'fun1' and type = 'p')
begin
drop procedure fun1,
print '已删除'
end
else
print '不存在,可创建'
-- 分析:经典的三表内联;再根据专业和姓名进行where筛选就可以了
-- 创建存储过程
create procedure fun1
@specialty nvarchar(10),
@stuName nvarchar(10)
as
begin
select stuId, stuName, stuAge, subName, score
from scoreInfo as sc
inner join studentInfo as stu on sc.stuId = stu.stuId
inner join subjectInfo as sub on sc.subId = sub.subId -- 三表内连
where stu.specialty = @specialty and stu.stuName = @stuName -- where筛选
end
-- 调用测试
exec fun1 '计算机','Loli1'
-- Q2: 创建一个名为fun2的存储过程,可查询某门课程考试的平均成绩
-- 注:平均成绩可以输出;平均成绩假定类型为int
create proc fun2
@subName nvarchar(10), -- 作为输入
@avg int output -- 作为输出(将结果带出去)
as
begin
set @avg =
select AVG(score)
from scoreInfo, subjectInfo
where scoreInfo.subId = subjectInfo.subId and subName = @subName
end
-- Q3:创建一个名为fun3的存储过程。输入学号@stuId、课程名称@subName作为参数值,
-- 将查询scoreInfo和subjectInfo表,并通过输出参数@score和@credit获取该学生该课程的成绩和学分。
-- 如果分数大于等于60,则返回对应课程的学分,否则返回学分值0。
-- 分析:两表内连后,查询到成绩;再根据成绩给credit赋值(case语句,if语句都可以)
create procedure fun3
@stdId int, -- 输入参数
@subName nvarchar(10), -- 输入参数
@score int output, -- 输出参数
@credit int output -- 输出参数
as
begin
select @score = sc.score, @credit = case when sc.score >= 60 then sub.credit else 0 end
from subjectInfo as sub, scoreInfo as sc
where sub.subId = sc.subId and sc.stuId = @stuId and subName = @subName
end
-- 分析:select的第一句很长但逻辑清晰;select不仅和print一样可以输出,本身也和set一样有赋值的意味
-- Q4:创建一个名为fun4的存储过程:既有输入又有输出,给出课程名称,统计输出该课程的各分数段人数
-- 分析:直接分组+sum聚合,这个思路是行不通的。问题出在分组依据———此时我们需要按范围进行分组。
-- 思路很巧妙:每统计一个范围的个数,就用case语句根据该范围将成绩转化为1和0,在进行sum(这样就统计出了每个范围的个数)
create procedure fun4
@subName nvarchar(10)
as
begin
select sc.subName as '课程名',
sum(case when score >= 90 then 1 else 0 end) as '[90+ 范围',
sum(case when score < 90 and score >= 80 then 1 else 0 end) as '[80, 90)范围',
sum(case when score < 80 and score >= 70 then 1 else 0 end) as '[70, 80)范围',
sum(case when score < 70 and score >= 60 then 1 else 0 end) as '[60, 70)范围',
sum(case when score < 60 then 1 else 0) as '(60-范围'
from subjectInfo, scoreInfo
where subjectInfo.subId = scoreInfo.subId and subName = @subName
group by subName
end