sql sever 练习

这篇博客涵盖了多个SQL Server操作的实例,包括创建视图、查询特定条件的学生成绩、事务处理、存储过程的编写、表的创建与关联、删除操作的影响、数据导入、游标应用、成绩分布统计以及触发器的设定。内容详细解析了各种SQL语句的用法和场景。
摘要由CSDN通过智能技术生成

数据库中有以下三个表:

学生基本情况表student_info

课程信息表curriculum

学生成绩表grade

请写出完成以下功能的SQL语句

1、创建一个视图,查询至少有5名学生选修的并以1开头的课程号的平均分。

create view view1
as
select 课程编号,avg(分数)a from grade a
where 课程编号 like '1%'
group by 课程编号
having count(*)>4

老师给的答案 

Create view ab
AS
Select 课程号,avg(分数) from grade
Where 课程号 like '1%'
Group by 课程号
Having count(*)>5

第一题答案与老师给的没多大区别。最后 having 语句可能是理解的不同吧。

2、查询选修“0001”课程的成绩高于“0002”号学生成绩的所有学生记录,并按成绩从高到低排列。

select 姓名,分数 
from student_info,grade
where student_info.学号 = grade.学号 and 课程编号='0001' and 分数>
    (select 分数 from grade where 课程编号='0001' and 学号='0002' )	
order by 分数 desc

老师给的答案  

Select x.课程号,x.学号,x.分数 
from grade x,grade y
Where x.课程号='0001'  and x.分数>y.分数
And y.学号='0002' and x.课程号='0001'
Order by x.分数 desc

出现两个x,y临时表,相当于分开用的两个grade表。

Select 课程号,学号,分数 from grade 
Where 课程号='0001'  and 分数>(Select 分数 from grade
where 学号='0002' and 课程号='0001')
Order by x.分数 desc

使用子查询的方法结构比较清晰。

3、开始一个事务,查询与学号为“0001”的学生同年出生的所有学生的学号,姓名和出生日期。并将0001号学生的家庭住址改为“广东省中山市”。提交事务。

begin transaction
    select 学号,姓名,出生日期 from student_info
    where year(出生日期)=(select year(出生日期) from student_info where 学号='0001')
    go
    update student_info
    set 家庭地址='广东省中山市'
    where 学号='0001'
    go
COMMIT TRANSACTION

老师给的答案  

Begin transaction
Select 学号,姓名,出生日期
From student_info 
Where year(出生日期)=(Select year(出生日期)
From student_info
Where 学号='0001')
Update student_info set 家庭住址='广东省中山市' where 学号='0001'
Commit transaction

4、创建一个存储过程,查询给定学号学生参加的所有课程的平均成绩,并返回其姓名及成绩等级,其中成绩等级以ABCD显示。

A等:[85-100]; B等:[75-85)

C等:[60,75); D等:<60

create procedure p_dingji @xuehao char(4)
as
declare @fenshu int
set @fenshu=(select avg(分数) from grade where 学号=@xuehao) 
select 姓名,
case 
 when @fenshu>=85 then 'A'
 when 85>@fenshu and @fenshu>=75 then 'B'
 when 75>@fenshu and @fenshu>=60 then 'C'
 when @fenshu<60 then 'D'
end as '成绩'
from student_info where 学号=@xuehao

一般写程序应该将85>@fenshu and @fenshu>=75 改为 @fenshu<85 and @fenshu>=75 来写才对。但是这里这样写好像是能运行的。

老师给的答案:

Create procedure proA @no char(4),@name char(10) output,@score char(2) output
AS
Select @name=姓名,@score=
Case
    When avg(分数)>=85 and avg(分数)<=100 then ‘A’
    When avg(分数)>=75 and avg(分数)<85 then ‘B’
    When avg(分数)>=60 and avg(分数)<75 then ‘C’
    When avg(分数)<60 then ‘D’
end
From student_info inner join grade
On student_info.学号=grade.学号
Where student_info.学号=@no
GROUP BY 姓名
GO

创建存储过程,设定参数。(后面加output用于返回值)。

老师这里的select是赋值用的,我的答案的select是查询用的。

5.  创建一个teacher表,有教师编号,教师姓名,性别,年龄,部门五个列,主键为教师编号,性别列取值为“男”或“女”。为curriculum表增加一列:教师编号,并建立curriculum表与teacher表的联系。

create table teacher(
教师编号 char(4)primary key,
教师姓名 char(10) ,
性别 char(2) check(性别='男' or 性别='女'),
年龄 int,
部门 varchar(20)
)
go
alter table curriculum 
add 教师编号 char(4) foreign key references teacher(教师编号)

老师给的答案:

Create table teacher(
   教师编号 char(4) primary key,
   教师姓名 varchar(20),
   性别 char(2) check(性别 in(‘男’ ,‘女’))
   年龄 int,
   部门 varchar(20)
)
Alter table curriculum
Add column 教师编号 char(4)
Alter table curriculum
Add constraint fk_c foreign key(教师编号) refereces teacher(教师编号)

 

老师这里的外键是在创建表后再把约束加上去。我是更改表结构创建列的时候直接加的。

6. 当删除student_info表中的学生信息时,同时删除grade表中的相关信息。

create trigger d_grade
on student_info after delete
as
delete grade where 学号 = (select 学号 from deleted)

老师给的答案:

CREATE  trigger stu_delete on student_info
After delete
AS
      declare @no varchar(5)
      SELECT @no=学号 FROM deleted
      DELETE FROM  grade WHERE 学号=@no
GO

没什么区别。上面用的是子查询找到刚刚删除的学号信息,来进行匹对。后面老师的是通过一个变量来完成信息的传递,将学号信息从deleted表传到grade表这样。

7. 新建一个表course,具有课程自动编号,课程名称,学分,教师编号四列。其中“课程自动编号”列为自动编号,其余三列从curriculum表中导入数据。

create table course(
课程自动编号 int identity(1,1) primary key,
课程名称 varchar(50),
学分 int,
教师编号 char(4)
)
go
insert into course(课程名称,学分,教师编号) select 课程名称,学分,教师编号 from curriculum 
go

老师给的答案:

Create table course(
课程自动编号 int identity(1,1),
课程名称 varchar(50),
学分 int,
教师编号 char(4))
Insert into course(课程名称, 学分, 教师编号)
Select课程名称, 学分, 教师编号from curriculum

使用 insert into……select 可以大批量的插入数据。

8. 使用游标,查询没有担任课程的教师编号,姓名及部门.

declare st_cursor1 cursor for select 教师编号,教师姓名,部门 
from teacher where 教师编号 in (select 教师编号 from curriculum)
open stu_cursor1
fetch next from stu_cursor
while @@FETCH_STATUS=0
begin
 fetch next from stu_cursor
end
close stu_cursor1

老师给的答案:

declare tea_cursor cursor scroll
for
select 教师编号,姓名,部门 from teacher where教师编号 not in
(select 教师编号from curriculum)
GO

OPEN tea_cursor              --打开游标  
FETCH NEXT FROM tea_cursor
WHILE @@FETCH_STATUS = 0          --FETCH语句执行成功  
    FETCH NEXT FROM tea_cursor 
CLOSE tea_cursor            
DEALLOCATE tea_cursor

9. 统计各门课程的成绩分布情况,即统计各分数段人数,显示:

课程编号,课程名称,[100-85],[85-70],[70-60],[ <60]

select curriculum.课程编号,课程名称,
sum(case when 分数>=85 and 分数<=100 then 1 else 0 end) '[100-85]',
sum(case when 分数>=70 and 分数<=84 then 1 else 0 end)'[84-70]',
sum(case when 分数>=60 and 分数<=69 then 1 else 0 end)'[69-60]',
sum(case when 分数<60 then 1 else 0 end) '[<60]'
from curriculum,grade
where curriculum.课程编号=grade.课程编号
group by curriculum.课程编号,课程名称

老师给的答案:

SELECT grade.课程编号,课程名称,
SUM(CASE WHEN 分数 BETWEEN 85 AND 100 THEN 1 ELSE 0 END) AS [100-85] ,
SUM(CASE WHEN 分数 BETWEEN 70 AND 85 THEN 1 ELSE 0 END) AS [85-70] ,
SUM(CASE WHEN 分数 BETWEEN 60 AND 70 THEN 1 ELSE 0 END) AS [70-60] ,
SUM(CASE WHEN 分数 < 60 THEN 1 ELSE 0 END) AS [<60] 
FROM grade inner join curriculum on grade.课程编号=curriculum.课程编号
GROUP BY grade.课程编号,课程名称

基本是一样的。利用case作判断,符合条件返回1这样,通过sum数出有多少个符合条件的

两边的'[100-85]'AS [100-85]其实效果是一样的。

除了用sum还有用count 也可以

select count(case when 分数>=85 then 学号 end)A,
count(case when (分数<85 and 分数>=70) then 学号 end)B,
count(case when (分数<70 and 分数>=60) then 学号 end)C,
count(case when 分数<60 then 学号 end)D
from grade

但原理解释起来很怪

10. 向grade表中插入一些记录,这些记录要求符合以下条件:没有上过编号“0003”课程的同学学号、0002号课的平均成绩.

insert into grade(学号,课程编号,分数) select 学号,
'X002',
(select avg(分数) from grade where 课程编号='0002') 
from student_info where 学号 not in (select 学号 from grade where 课程编号='0003')

老师给的答案:

Insert grade(学号,课程编号,分数)
select 学号,'0002',(Select avg(分数) from grade where 课程编号='0002') 
from Student_info 
where 学号 not in (Select 学号 from grade where 课程编号='0003')

按照我的理解就是学号为课程编号0003没有成绩的,分数统一为平均分这样。由于grade表不能少了课程编号,所以插入的数据除学号和分数插多一个课程编号。考虑到没有0003成绩的学生会有0002的,所以课程编号用x002代替。

11. 建立触发器,当向curriculum表插入课程信息时,承担课程的教师只允许插入现有教师信息.

create trigger tr_i_laoshi
on curriculum after insert
as
begin
 declare @bianhao char(4)
 select @bianhao= inserted.教师编号 from inserted
 if not exists(
 select 教师编号 
 from teacher 
 where 教师编号=@bianhao
 )
 begin
 raiserror('输入的教师编号不存在',16,1)
 rollback
 end
end

老师给的答案:

Create trigger tri_ins on curriculum
After insert
AS
  declare @teano varchar(4)
  SELECT @teano=教师编号 FROM inserted
  IF not exists (SELECT * FROM teacher WHERE教师编号=@teano)
  Print(‘指定插入的教师编号不存在!请确认后重新插入!’)

Rollback

GO

 

SQL是高级的非过程化编程语言,是沟通数据库服务器和客户端的重要工具,允许用户在高层数据结构上工作。它不要求用户指定对数据的存放方法,也不需要用户了解具体的数据存放方式,所以,具有完全不同底层结构的不同数据库系统,可以使用相同的SQL语言作为数据输入与管理的SQL接口。 它以记录集合作为操作对象,所有SQL语句接受集合作为输入,返回集合作为输出,这种集合特性允许一条SQL语句的输出作为另一条SQL语句的输入,所以SQL语句可以嵌套,这使它具有极大的灵活性和强大的功能,在多数情况下,在其他语言中需要一大段程序实现的功能只需要一个SQL语句就可以达到目的,这也意味着用SQL语言可以写出非常复杂的语句。    结构化查询语言(Structured Query Language)最早是IBM的圣约瑟研究实验室为其关系数据库管理系统SYSTEM R开发的一种查询语言,它的前身是SQUARE语言。SQL语言结构简洁,功能强大,简单易学,所以自从IBM公司1981年推出以来,SQL语言得到了广泛的应用。如今无论是像Oracle、Sybase、DB2、Informix、SQL Server这些大型的数据库管理系统,还是像Visual Foxpro、PowerBuilder这些PC上常用的数据库开发系统,都支持SQL语言作为查询语言。    美国国家标准局(ANSI)与国际标准化组织(ISO)已经制定了SQL标准。ANSI是一个美国工业和商业集团组织,负责开发美国的商务和通讯标准。ANSI同时也是ISO和International Electrotechnical Commission(IEC)的成员之一。ANSI 发布与国际标准组织相应的美国标准。1992年,ISO和IEC发布了SQL国际标准,称为SQL-92。ANSI随之发布的相应标准是ANSI SQL-92。ANSI SQL-92有时被称为ANSI SQL。尽管不同的关系数据库使用的SQL版本有一些差异,但大多数都遵循 ANSI SQL 标准。SQL Server使用ANSI SQL-92的扩展集,称为T-SQL,其遵循ANSI制定的 SQL-92标准。    SQL语言包含4个部分:    数据定义语言(DDL),例如:CREATE、DROP、ALTER等语句。    数据操作语言(DML),例如:INSERT(插入)、UPDATE(修改)、DELETE(删除)语句。    数据查询语言(DQL),例如:SELECT语句。    数据控制语言(DCL),例如:GRANT、REVOKE、COMMIT、ROLLBACK等语句。    SQL语言包括三种主要程序设计语言类别的语句:数据定义语言(DDL),数据操作语言(DML)及数据控制语言(DCL)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值