数据库应用与开发【实验题汇总】

文章目录

  • 实验1 认识SQL Server 2106 的运行环境
  • 实验2 创建与管理数据库
  • 实验3.1 表的创建与维护
  • 实验3.2 表的创建与维护
  • 实验4.1 Transact-SQL语句基础
  • 实验4.2 控制流语句编程
  • 实验5 针对Teaching数据库,完成以下查询
  • 实验6.1 利用Teaching数据库完成以下查询
  • 实验6.2 游标
  • 实验8.1 创建索引
  • 实验8.2 视图的建立
  • 实验9.1 存储过程
  • 实验9.2 触发器
  • 实验9.3 存储过程附加
  • 实验10 事务定义
  • 实验11 锁
  • 实验13 SQL server安全管理

实验1 认识SQL Server 2106 的运行环境

实验目的:掌握SQL Server Management Studio集成环境的构成和基本操作,熟悉服务器管理和基本操作,熟悉联机丛书与教程的使用。
实验步骤:
(1)SQL Server Management Studio的启动和退出
1)启动SQL Server Management Studio
2)连接服务器选择
3)连接服务器的属性设置
4)身份验证选择
5)连接
6)退出SQL Server Management Studio
数据库应用与开发【实验题汇总】_第1张图片

(2)SQL Server Management Studio的基本操作
1)菜单栏的操作
2)工具栏的操作
3)“已注册的服务器”窗口
4)“对象资源管理器”窗口
5)“文档”窗口
6)属性窗口
7)模板资源管理器

(3)新建查询
1)打开查询编辑器代码窗口
2)输入一条SQL查询语句
3)执行该脚本
数据库应用与开发【实验题汇总】_第2张图片

(4)注册SQL Server 2016服务器
1)打开“已注册的服务器”窗口
2)弹出“新建服务器注册”对话框
3)输入服务器名称及其身份验证方式
4)在“已注册的服务器名称”文本框中输入管理的服务器名称,可以使用默认的服务器实例名,也可以重新命名。
5)单击测试按钮,成功后单击确定返回“新建服务器注册”对话框。

6)在“新建服务器注册”对话框中切换至“连接属性”选项卡,可设置注册服务器的相关属性。

7)单击保存按钮,完成服务器注册操作。

(5)启动和停止SQL Server 2016服务器
1)使用SQL Server配置管理器完成。
数据库应用与开发【实验题汇总】_第3张图片

2)使用SQL Server Management Studio完成。

3)使用SQL Server服务完成

(6)配置SQL Server 2016服务器
启动SQL Server Management Studio,在对象资源管理器中单击已连接的服务器,打开服务器属性窗口完成配置。

(7)SQL Server 2016联机丛书和教程的使用
(8)理解model数据库的作用
1)在model数据库中创建模式S_T,用户表S_T.s、S_T.sc和S_T.c(表结构参照上学期数据库原理教材中表结构)
数据库应用与开发【实验题汇总】_第4张图片

2)创建数据库student,查看该数据库中的数据表和模式。


2)为student数据的s表键入自己的信息

数据库应用与开发【实验题汇总】_第5张图片

实验2 创建与管理数据库

创建与管理数据库
(1) 利用Transact-SQL语句创建一个名为CPChistory的数据库。该数据库的主数据库文件逻辑名称为CPChistory,初始大小为10MB,最大尺寸为无限大,增长速度为10%;数据库的日志文件逻辑名称为CPChistory_log,初始大小为1MB,最大尺寸为5MB,增长速度为1MB。存放路径为D:\DATA\,其他均采用默认设置。

(2) 利用Transact-SQL语句增加文件组filegroup1,添加次要数据文件CPChistory2放入文件组filegroup1中,添加逻辑名称为CPChistory2_log的日志文件,文件均放在D:\DATA\目录下。

在这里插入图片描述
数据库应用与开发【实验题汇总】_第6张图片

数据库应用与开发【实验题汇总】_第7张图片

(3) 利用Transact-SQL语句创建数据库test,采用默认参数。若该数据库已存在,则删除后重建。

if exists(select * from sys.databases where name = 'test')
drop database test
create database test

(4)修改数据库test,将数据文件的逻辑文件名修改为“测试数据”,操作系统文件名修改成D:\DATA\test.MDF。将事务日志文件的逻辑文件名修改为“测试数据日志”,操作系统文件名修改成D:\DATA\test_log.LDF。并且为数据库新增一个逻辑名为“测试数据2”的次要数据文件。

数据库应用与开发【实验题汇总】_第8张图片

(5)利用SQL Server Management Studio将test数据库分离后重新附加到当前SQL Server实例中。


(6)利用Transact-SQL语句将test数据库重命名为“测试”,调用系统存储过程将“测试”重命名为test。

(7)利用Transact-SQL语句为数据库CPChistory和test创建快照。



在这里插入图片描述

(8)利用Transact-SQL语句删除创建的数据库CPChistory和test。

alter database CPChistory remove file CPChistory2

实验3.1 表的创建与维护

实验三 表的创建与维护
(1)利用SQL Server Management Studio自定义数据类型sex_type,类型为nchar(1);数据库应用与开发【实验题汇总】_第9张图片


数据库应用与开发【实验题汇总】_第10张图片

(2)利用Transact-SQL语句创建表“人物”“部队”“战役”“属于”(表结构见作业的参考答案),性别属性的数据类型设置为sex_type),注意主外键的设置。
数据库应用与开发【实验题汇总】_第11张图片

数据库应用与开发【实验题汇总】_第12张图片

(3)利用Transact-SQL语句修改为表“人物”增加属性“民族”,类型为nchar(8),设置not null 约束。

(4)利用Transact-SQL语句为表“人物”的姓名属性增加唯一约束;
为“战役”表的“胜败”列创建check约束,规定取值为“胜”“败”“平”。

数据库应用与开发【实验题汇总】_第13张图片

(4)为“人物”表插入如下数据:1)将插入的信息输出到表变量@people;2)浏览表变量中的信息。
编号 姓名 出生年月 性别 党派 民族
2 周恩来 1898-3-5 男 中国共产党 汉族
3 朱德 1886-12-1 男 中国共产党 汉族
4 张闻天 1900-8-30 男 中国共产党 汉族
5 王稼祥 1906-8-15 男 中国共产党 汉族
6 刘伯承 1892-12-4 男 中国共产党 汉族
为“属于”表输入如下数据:
人物编号 部队编号 开始时间 结束时间 任职
6 KR129 1937-8-25


数据库应用与开发【实验题汇总】_第14张图片
数据库应用与开发【实验题汇总】_第15张图片

(5)根据“人物”和“属于”两个关系,在“属于”关系中将刘伯承在KR129师的任职改为“师长”。

数据库应用与开发【实验题汇总】_第16张图片

(7)创建excle文档,数据结构如下,然后将其导入数据库,建立“参战”表。
部队编号 战役名称 参加人数 损失人数
KR129 淞沪会战 NULL NULL
KR120 百团大战 400000 17000

选做:通过学习联机帮助完成以下操作:
创建student表(表结构如表4-8(82页)),使其按照学号进行分区,N0001-N0400放在primary文件组,N0401-N800放在filegroup1,N800以上的放在filegroup2
命令提示:
1.CREATE PARTITION FUNCTION
2.CREATE PARTITION SCHEME
3.CREATE TABLE



数据库应用与开发【实验题汇总】_第17张图片


在这里插入图片描述

数据库应用与开发【实验题汇总】_第18张图片

实验3.2 表的创建与维护

实验三
(1)利用SQL Server Management Studio自定义数据类型grade_type,类型为numeric(5,2)。
数据库应用与开发【实验题汇总】_第19张图片

(2)利用Transact-SQL语句创建表student(表结构如表4-8(82页))、course(表结构如表4-9)和表score(表结构如表4-10,usually和final属性的数据类型设置为grade_type),注意主外键的设置。

(3)向student表输入如下数据
studentno sname sex birthdate classno
1 张三 男 2000-3-7 1
2 李四 男 2002-6-1 2
3 王五 男 2001-7-7 2
4 赵华 女 2001-8-21 3
数据库应用与开发【实验题汇总】_第20张图片

(4)查询student表,输出前3条记录。

(5)修改score表,将usually改为“平时成绩”,并增加计算列“总评”,使其值为平时成绩的40%加上final的60%。

alter table score
add 总评 as (平时成绩 * 0.4 + final * 0.6) persisted

数据库应用与开发【实验题汇总】_第21张图片

数据库应用与开发【实验题汇总】_第22张图片

(6)阅读下面语句,写出每个语句的作用
declare @var_student table(sno nchar(11));
声明表变量@var_student
Insert top(3) into @var_student select sno from student;
插入数据,同时将插入行的前三行放入表变量@var_student中
Select * from @var_student table;
查询表变量中的值

实验4.1 Transact-SQL语句基础

实验四-1 Transact-SQL语句基础

  1. 变量的应用

定义变量 @sno CHAR(8)
@name VARCHAR(10)
@sex NCHAR(2)
@birthday DATETIME

使用set 和 select 用自己的信息赋值
打印 @sno+@name+@sex
打印 @birthday

declare @sno char(12), @name varchar(10), @sex nchar(2), @birthday datetime
set @sno = '202012304054'
set @name = '洋溢'
set @sex = '女'
set @birthday = '2002-8-4'

select @sno+@name+@sex
select @birthday

(2)运算符的应用
–算术运算符
打印 当前日期后100天的日期
打印 123+23%10/7+(17-6)*2.5

print dateadd(day, 100, getdate())
print 123+23%10/7+(17-6)*2.5

–字符串连接运算符

定义变量 @A CHAR(5)
@B VARCHAR(5)
@C INT
@D DECIMAL(5,2)
赋值 @A=‘123’
@B=‘456.5’
@C=123
@D=456.5
打印 @A+@B
@A+@D
@C+@D
赋值 @A=‘数据库’
@B=‘程序开发’
打印 @A+@B
打印 @A+@D

declare @A CHAR(5), @B VARCHAR(5), @C INT, @D DECIMAL(5,2)

set @A = '123'
set @B = '456.5'
set @C = 123
set @D = 456.5

print @A + @B
print @A + @D
print @C + @D

set @A = '数据库'
set @B = '程序开发'

print @A + @B
print @A + cast(@D as VARCHAR(10))
print @A + @D

–位运算符
定义变量 @A INT
@B INT
赋值 @A=5
@B=12
打印 @A&@B
@A|@B
@A^@B
~@A

declare @A INT, @B INT
set @A = 5
set @B = 12
print @A & @B
print @A | @B
print @A ^ @B
print ~ @A

–(3)系统函数的应用
–数学函数
打印 CEILING(16.3)
CEILING(-16.8)
CEILING(0.0)
FLOOR(16.3)
FLOOR(-16.8)
FLOOR(0.0)
ROUND(123.456,2)
ROUND(123.456,-1)
ROUND(123.456,-2)
ROUND(123.456,-4)
ROUND(175.86,0)
ROUND(175.86,0,1)

print CEILING(16.3)
print CEILING(-16.8)
print CEILING(0.0)
print FLOOR(16.3)
print FLOOR(-16.8)
print FLOOR(0.0)
print ROUND(123.456,2)
print ROUND(123.456,-1)
print ROUND(123.456,-2)
print ROUND(123.456,-4)
print ROUND(175.86,0)
print ROUND(175.86,0,1)

–转换函数
定义变量 @count INT
@date DATETIME
赋值 @count=255
@date=GETDATE()
打印 @count转换为字符串打印
打印’2016-12-25’后100天的时间(转换成日期型打印)
将@date转换成字符串打印

declare @count int, @date datetime
set @count = 255
set @date=getdate()
print cast(@count as varchar(12))
print dateadd(day, 100, 2016-12-25)
print cast(@date as varchar(12))

–字符串函数
定义变量 @str NCHAR(25)
赋值 @str=‘SQL SERVER 2008数据库应用与开发’
打印 @str 的长度
‘数据库’在@str中的起始位置
将@str中’开发’替换成’设计’)

declare @str nchar(25)
set @str = 'SQL SERVER 2008数据库应用与开发'
print len(@str)
print replace(@str, '开发', '设计')

实验4.2 控制流语句编程

实验四 控制流语句编程
1.编程求50~100之间所有能被3整除的奇数之和。(必做)

declare @sum int = 0
declare @n int = 50
while @n >= 50 and @n <= 100
begin
	if @n % 3 = 0
		set @sum = @sum + @n
	set @n = @n + 1
end
print @sum

2.编写程序根据姓名查询teaching数据库(相关表信息见教材82-88页表4-8至表4-13,下同)中学生的基本信息和选课信息,学生姓名通过变量输入。对不存在的学生,打印提示信息。(提示:定义局部变量@same,将自己的姓名赋值给局部变量@same)(必做)

declare @same nchar(8) = '竹云泽'
if exists (select * from student where @same = sname)
begin
	select distinct student.*, course.*
	from student, course, score
	where student.sname = @same and student.studentno = score.studentno and score.courseno = course.courseno
end
else
	print '不存在' + rtrim(@same)+ '该同学信息'
  1. 编写程序查询所有学生选修课程的期末成绩和对应等级,如学生未选修任何课程则输出提示信息。(提示:使用case语句根据成绩来确定其等级,如果没有成绩则打印未选修)(必做)
    (期末成绩>=90 对应等级为“优”,
    90>期末成绩>=80 对应等级为“良”,
    80>期末成绩>=70 对应等级为“中”,
    70>期末成绩>=60 对应等级为“及格”,
    期末成绩<60 对应等级为“不及格”)
select distinct studentno '学号', courseno '课程号', final '分数'	,
	case
		when final >= 90 then '优'
		when final >= 80 then '良'
		when final >= 70 then '中'
		when final >= 60 then '及格'
		when final < 60 then '不及格'
		when final is null then '未选修'
	end '等级'
from score
  1. 编写程序判断字符变量@ch中存放的是字母字符、数字字符还是其他字符,并输出相关信息。(必做)
declare @ch char = 'a'
if upper(@ch) >= 'A' and upper(@ch) <= 'Z'
	print @ch + '是字母字符'
else if @ch >= '0' and @ch <= '9'
	print @ch + '是数字字符'
else
	print @ch + '是其他字符'
  1. 建立数据库charge,建立数据表water(用户编号,年,月,用水量)。(要求利用case 语句)
    为鼓励居民节约用水,很多城市实行了阶梯水费的收缴形式。以桂林为例,居民生活用水费的收费标准为,每户月用水量,在32立方米以内时,每立方米收费1.47元,超过32立方米但小于48立方米时,超出的部分,按每立方米2.21元收费,超过48立方米时,超出的部分,按每立方米2.94元收费。编写程序,输出用户用水情况,并根据用户的用水量,计算并显示其对应的水费。
select distinct 用户编号, 用水量,
	case
		when 用水量 <= 32 then 用水量 * 1.47
		when 用水量 > 32 and 用水量 <= 48 then 32 * 1.47 + (用水量 - 32) * 2.21
		when 用水量 > 48 then 32 * 1.47 + (48 - 32) * 2.21 + (用水量 - 48) * 2.94
	end 水费
from water
  1. 给定一行字符串,分别统计出其中英文字母、空格、数字和其它字符的个数。(要求运用字符串函数)
declare @pos bigint = 1, @len bigint, @char nvarchar(1), @text nvarchar(max)
declare @letters bigint = 0, @numbers bigint = 0, @spaces bigint = 0, @others bigint = 0
set @text = '123q we ! @ #'
set @len = len(@text)
while @pos <= @len
begin
	set @char = substring(@text, @pos, 1)
	if @char = ' ' 
		set @spaces += 1
	else if upper(@char) >= 'A' and upper(@char) <= 'Z'
		set @letters += 1
	else if @char >= '0' and @char <= '9'
		set @numbers += 1
	else
		set @others += 1
	set @pos = @pos + 1 -- 
end

print 'letters:' + cast(@letters as nvarchar(2)) 
print 'numbers:' + cast(@numbers as nvarchar(2))
print 'spaces:' + cast(@spaces as nvarchar(2))
print 'others:' + cast(@others as nvarchar(2))
  1. 打印出如下图案(菱形)(要求利用while语句)
    在这里插入图片描述
declare @a int = 1, @b int = 7
while @a < @b
begin
	if @a % 2 = 1
		print space((@b - @a) / 2) + replace(space(@a), ' ', '*') + space((@b - @a) / 2)
	set @a += 1
end

while @a <= @b
begin
	if @a % 2 = 1
		print space((@b - @a) / 2) + replace(space(@a), ' ', '*') + space((@b - @a) / 2)
	set @a -= 1
	if @a < 0
		break
end
  1. 编写程序将十进制整数转换为二进制字符串后输出。(选做)
declare @ch nchar(10) = ' ', @n int = 10, @a int
while @n <> 0
begin
	set @a = @n % 2
	set @n = @n / 2
	set @ch = char(48 + @a) + @ch
end
print @ch
  1. 编写程序求解如下分数序列的前n项之和并打印输出结果,n由变量输入。(选做)
    数据库应用与开发【实验题汇总】_第23张图片
declare @n float = 2, @sum float = 0, @t float, @分子 float = 2, @分母 float = 1
set @t = @n
while @t > 0
begin
	set @sum = @sum + @分子 / @分母
	set @分子 = @分子 + @分母
	set @分母 = @分子 - @分母
	set @t -= 1
end
print @sum

实验5 针对Teaching数据库,完成以下查询

实验五
针对Teaching数据库,完成以下查询:
(1)查询选修课程且期末成绩不为空的学生人数。

select distinct count(studentno) 人数
from course, score
where course.courseno = score.courseno and score.final is not null and course.courseno in (
	select courseno
	from course
	where type = '选修'
)

(2)查询所有Email使用126邮箱的学生的学号、姓名和电子邮箱地址。

select studentno, sname, Email
from student
where Email like '%126%'

(3)查询每名学生的学号、选修课程数目、总成绩,并将查询结果存放到生成的“学生选课统计表”中。

if exists (select * from sys.objects where name = '学生选课统计表')
drop table 学生选课统计表

select studentno, count(*) '学生选课数目', sum(final) '总成绩' into 学生选课统计表
from score
group by studentno

select * from 学生选课统计表

(4)查询选修’c05109’课程,并且期末成绩在前5名的学生学号、课程号和期末成绩。

select top(5) studentno, courseno, final
from score
where courseno = 'c05109'
order by final desc

(5)查询教授两门及以上课程的教师编号、课程编号和任课班级。

select teacherno, courseno, classno
from teach_class
where teacherno in (
	select teacherno
	from teach_class
	group by teacherno
	having count(courseno) >= 2
)

(6)查询课程编号以’c05’开头,被三名及以上学生选修,且期末成绩的平均分高于75分的课程号、选修人数和期末成绩平均分,并按平均分的降序排序。

select courseno, count(studentno) 选修人数, avg(final) 期末平均分
from score
where courseno like 'c05%' and final is not null
group by courseno
order by avg(final) desc

(7)查询每个教师的授课门数及所有老师的授课总门数。

select teacherno, count(courseno) 授课门数
from teach_class
group by teacherno

select count(courseno) 授课总门数
from teach_class

(8)P161(4)按性别分组,求出student表中每组学生的平均年龄。
数据库应用与开发【实验题汇总】_第24张图片

P161(5)利用现有的表生成新表,新表中包括学号、学生姓名,课程号和总评成绩。其中,总评成绩=final * 0.8 + daily * 0.2。

select student.studentno, sname, courseno, final * 0.8 + usually * 0.2 总评
into student_score
from student, score
where student.studentno = score.studentno

select * from student_score

(9)P161(6)统计每个学生的期末成绩平均分。

select studentno, avg(final)
from score
group by studentno

(10)P161(7)输出student表中年龄最大男生的所有信息。

select *
from student
where sex = '男' and datediff(year, birthday, getdate()) >= (
	select max(datediff(year, birthday, getdate()))
	from student
	where sex = '男'
)

实验6.1 利用Teaching数据库完成以下查询

实验六-1
利用Teaching数据库完成以下查询。
(1)查询教师基本信息和教授课程信息,其中包括未分配课程的教师信息。

select teacher.*, teach_class.courseno
from teacher
left join teach_class on teacher.teacherno = teach_class.teacherno
left join course on teach_class.courseno = course.courseno

(2)查询所有班级期末平均成绩的最高分,并将其赋值给变量,通过PRINT语句输出。

declare @max numeric(6,2)
select  @max = max(平均分) 
from(
	select classno as 班级号, avg(final) as 平均分
	from score
	join student on( score.studentno=student.studentno)
	where final is not null
	group by classno)t
print '所有班级期末平均成绩的最高分:'+cast(@max as varchar(6))

(3)查询16级学生的学号、姓名、课程名及学分。

select student.studentno,sname,cname,credit
from score
join student on student.studentno = score.studentno
join course on course.courseno= score.courseno
where student.studentno like '16%' 

(4)P186 3(2)
在这里插入图片描述

select distinct student.studentno,student.sname,
	course.cname,score.final * 0.9 + score.usually * 0.1 as '总评'
into student_course
from student,course,score
where student.studentno = score.studentno 
	and course.courseno = score.courseno
select * from student_course

(5)P186 3(3)
在这里插入图片描述

select student.studentno, count(*) as '课程门数'
from score
join student on student.studentno = score.studentno
where score.final > 75 
group by student.studentno
或者
select student.studentno, count(*) as '课程门数'
from student,score
where score. final > 75 and student.studentno = score.studentno
group by student.studentno

(6)P186 3(4)
在这里插入图片描述

select *
from student
where sex='男' and datediff(day, birthday, getdate()) > (
	select avg(datediff(day, birthday, getdate()))
	from student
	where sex ='女')

(7)P186 3(5)
在这里插入图片描述

select student.studentno,student.sname,sum(credit) 学分
from student 
	join score on student.studentno = score.studentno 
	join course on course.courseno= score.courseno
where score.final > 60
group by student.studentno,student.sname

(8)P186 3(8)
在这里插入图片描述

select studentno, count(*) num into cnt
from score
group by studentno
select distinct student.studentno,sname,phone,Email
from student 
join score on student. studentno = score.studentno 
join cnt on student.studentno = cnt.studentno
where score.final < 60 or num< 3

实验6.2 游标

实验六-2游标
(1)使用游标输出学生姓名、选修课程名称和期末考试成绩,按如下格式输出。

学生姓名 课程名称 期末成绩
XXXX XXXX XXXX
XXXX XXXX XXXX
XXXX XXXX XXXX

print'姓名    课程           期末成绩'
print('-------------------------------------------')
declare @sname varchar(20),@cname varchar(20),@final varchar(20)
declare stu_cursor cursor
for select sname,cname,final
from student a join score b on a.studentno=b.studentno join course c on b.courseno=c.courseno
open stu_cursor
fetch next from stu_cursor into @sname,@cname,@final
while @@fetch_status=0
	begin
		print @sname+@cname+@final
		fetch next from stu_cursor into @sname,@cname,@final
	end
close stu_cursor
deallocate stu_cursor

(2)使用游标计算学生期末成绩的等级(大于等于90为优秀,大于等于80小于90为良好,大于等于70小于80为中等,大于等于60小于70为及格,小于60为不及格)。
①在score表中新增等级字段level。
②使用游标计算学生期末成绩的等级,并更新level列。
③查看使用游标修改数据表后的结果。

declare @usually numeric(6, 2),@final numeric(6, 2), @leve nchar(6)
declare score_cursor cursor
for select  final,usually,leve from score
open score_cursor
fetch next from score_cursor into @final,@usually, @leve
while @@fetch_status=0
	begin
		select @final, @usually, @leve
		if(@final * 0.9 + @usually * 0.1 >= 90)
			update score set leve='优秀'
			where current of score_cursor
		else if(@final * 0.9 + @usually * 0.1 >= 80)
			update score set leve='良好'
			where current of score_cursor
		else if(@final * 0.9 + @usually * 0.1 >= 70)
			update score set leve='中等'
			where current of score_cursor
		else if(@final * 0.9 + @usually * 0.1 >= 60)
			update score set leve='及格'
			where current of score_cursor
		else
			update score set leve='不及格'
			where current of score_cursor
		fetch next from score_cursor into @final,@usually, @leve
	end
close score_cursor
deallocate score_cursor

(3)开课表(开课号、课程号、教师号、开课地点、开课学年、开课学期、开课周数、开课时间、限选人数、已选人数)选课表(学号、开课号、成绩)
题目:开课表中,由于每一个开课号有人数限制,当学生选课确定后,需和该开课号的限选人数相对比,如果没有超过限选人数,则已选人数修改为实际选课人数,否则打印“这个开课计划选择的人数已经超过限选人数,请调整!”。使用游标逐个检查并修改每个开课号在选课表中的学生选修人数,并显示输出。

declare @courseno nchar(11), @stunumber tinyint, @total tinyint
declare course_cursor cursor
for select  courseno,period from course
open course_cursor
fetch next from course_cursor into @courseno,@stunumber
while @@fetch_status=0
	begin
		select @courseno,@stunumber
		--定义内层游标
		declare stu_cursor cursor
		for 
			select count(studentno) as 'total'
			from score
			where score.courseno = @courseno
			group by courseno
		open stu_cursor
		fetch next from stu_cursor into @total
		while @@fetch_status=0
			begin
				if @total > @stunumber print '这个开课计划选择的人数已经超过限选人数,请调整!'
				if @total < @stunumber 
					update course set period=@total
					where current of course_cursor
				fetch next from stu_cursor into @total
			end
			close stu_cursor
			deallocate stu_cursor
		--内层游标结束

		fetch next from course_cursor into @courseno,@stunumber
	end
close course_cursor
deallocate course_cursor

(4)学生选课管理中,当学生选修某门课分数不低于60时才能获得学分。检查学生获得的学分数是否正确,如果不正确,则进行修改。
学生表(学号,姓名,性别,专业,院系,累计学分)
选课表 (学号、开课号、成绩)
开课表(开课号、课程号、教师号、开课地点、开课学年、开课学期、开课周数、开课时间、限选人数、已选人数)
课程表(课程号、课程名称、学分)
–生成绩点表

select distinct student.studentno,student.sname,course.cname,
	score.final * 0.9+ score.usually * 0.1 as '总评',
	(score.final * 0.9+ score.usually * 0.1)/10-5 as 'credit' into student_corse2
from student,course,teach_class,score
where student.studentno = score.studentno and course.courseno = score.courseno

select *
from student_corse2
--检查学分
declare @总评 numeric(6, 2),@credit numeric(6, 2)
declare score_cursor cursor
for select 总评, credit from student_corse2
open score_cursor
fetch next from score_cursor into @总评, @credit
while @@fetch_status=0
	begin
		select @总评, @credit
		if(@总评 < 60)
			update student_corse2 set credit=0
			where current of score_cursor
		fetch next from score_cursor into @总评, @credit
	end
close score_cursor
deallocate score_cursor

(5)某同学建立了学生表,由于没有设置主键,因此表中存在很多重复的记录。现在需要对表中数据进行清洗,去掉重复记录,对于重复的取值,仅保留一条记录。请利用游标完成。

declare @studentno1 nchar(11),@studentno2 nchar(11)
declare stu_cursor1 cursor
for select studentno from student
open stu_cursor1
fetch next from stu_cursor1 into @studentno1
while @@fetch_status=0
	begin
		select @studentno2
		--定义内层游标
		declare stu_cursor2 cursor
		for 
			select studentno as 'studentno2'
			from student
		open stu_cursor2
		fetch next from stu_cursor2 into @studentno2
		while @@fetch_status=0
			begin
				if(@studentno1 = @studentno2)
					delete from student where studentno = @studentno2
				fetch next from stu_cursor2 into @studentno2
			end
			close stu_cursor2
			deallocate stu_cursor2
		--内层游标结束
		fetch next from stu_cursor1 into @studentno1
	end
close stu_cursor1
deallocate stu_cursor1

(6)针对已经建好如下的本地游标和全局游标,利用sp_cursor_list函数返回所有可视的全局游标列表及其特性,利用sp_describe_cursor_columns和sp_describe_cursor_tables函数返回所有可视的本地游标的情况。

declare @teacherno nchar(6),@tname nchar(8)
declare teacher_cursor cursor
for select teacherno,tname FROM teacher
declare @teacher_cursor cursor
exec teaching.dbo.sp_cursor_list
	@cursor_return = @teacher_cursor output,cursor_scope = 2
open teacher_cursor
fetch next from teacher_cursor into @teacherno,@tname
while @@fetch_status = 0
	begin
		fetch next from teacher_cursor
	end
close @teacher_cursor
deallocate @teacher_cursor
--sp_describe_cursor_columns
declare @x_cursor  cursor
declare student_cursor cursor
for
select studentno, sname
from student
open student_cursor
EXEC  sp_describe_cursor_columns  @cursor_return=@x_cursor OUTPUT, @cursor_source=N'global', @cursor_identity= N'student_cursor' 
fetch next from student_cursor  --使得@@FETCH_STATUS=0
while @@FETCH_STATUS=0
begin
  fetch next from @x_cursor
end
close @x_cursor
deallocate @x_cursor
deallocate student_cursor

1)本地游标cur_score,输出学生姓名、选修课程名称和期末考试成绩

print'姓名    课程          期末成绩'
print('-------------------------------------------')
declare @sname varchar(20),@cname varchar(20),@final varchar(20)
declare cur_score cursor
for select sname,cname,final
from student a join score b on a.studentno=b.studentno join course c on b.courseno=c.courseno
open cur_score
fetch next from cur_score into @sname,@cname,@final
while @@fetch_status=0
	begin
		print @sname+@cname+@final
		fetch next from cur_score into @sname,@cname,@final
	end
close cur_score
deallocate cur_score

2)本地游标cur_score_update,计算学生期末成绩的等级,并更新level列

declare @usually numeric(6, 2),@final numeric(6, 2), @level nchar(11)
declare cur_score_update cursor
for select  final,usually,level from score
open cur_score_update
fetch next from cur_score_update into @final,@usually, @level
while @@fetch_status=0
	begin
		select @final, @usually, @level
		if(@final * 0.9 + @usually * 0.1 >= 90)
			update score set level='优秀'
			where current of cur_score_update
		else if(@final * 0.9 + @usually * 0.1 >= 80)
			update score set level='良好'
			where current of cur_score_update
		else if(@final * 0.9 + @usually * 0.1 >= 70)
			update score set level='中等'
			where current of cur_score_update
		else if(@final * 0.9 + @usually * 0.1 >= 60)
			update score set level='及格'
			where current of cur_score_update
		else
			update score set level='不及格'
			where current of cur_score_update
		fetch next from cur_score_update into @final,@usually, @level
	end
close cur_score_update
deallocate cur_score_update

3)全局游标cur_stunum_update,检查修改每个开课号在选课表中的学生选修人数

declare @courseno nchar(11), @stunumber tinyint, @total tinyint
declare cur_stunum_update cursor
for select  courseno,period from course
open cur_stunum_update
fetch next from cur_stunum_update into @courseno,@stunumber
while @@fetch_status=0
	begin
		select @courseno,@stunumber
		--定义内层游标
		declare stu_cursor cursor
		for 
			select count(studentno) as 'total'
			from score
			where score.courseno = @courseno
			group by courseno
		open stu_cursor
		fetch next from stu_cursor into @total
		while @@fetch_status=0
			begin
				if @total > @stunumber print '这个开课计划选择的人数已经超过限选人数,请调整!'
				if @total < @stunumber 
					update course set period=@total
					where current of cur_stunum_update
				fetch next from stu_cursor into @total
			end
			close stu_cursor
			deallocate stu_cursor
		--内层游标结束

		fetch next from cur_stunum_update into @courseno,@stunumber
	end
close cur_stunum_update
deallocate cur_stunum_update

4)全局游标cur_credit_check,检查学生获得的学分数是否正确,如果不正确,则进行修改

declare @总评 numeric(6, 2),@credit numeric(6, 2)
declare cur_credit_check cursor
for select 总评, credit from student_corse2
open cur_credit_check
fetch next from cur_credit_check into @总评, @credit
while @@fetch_status=0
	begin
		select @总评, @credit
		if(@总评 < 60)
			update student_corse2 set credit=0
			where current of cur_credit_check
		fetch next from cur_credit_check into @总评, @credit
	end
close cur_credit_check
deallocate cur_credit_check

(7)在学生表增加一个字段“预警级别”,然后编写游标对每个学生已修课程成绩进行检测,统计累计所欠学分,达到20分的学生,修改“预警级别”为“学业警示”,达到30分的学生,修改“预警级别”为“编入下一年级”。

declare @累计学分 numeric(6, 2),@预警级别 nchar(11)
declare score_cursor cursor
for select  累计学分,预警级别 from student
open score_cursor
fetch next from score_cursor into @累计学分,@预警级别
while @@fetch_status=0
	begin
		select @累计学分,@预警级别
		if(@累计学分>=20)
			update student set 预警级别='学业警示'
			where current of score_cursor
		if(@累计学分>=30)
			update student set 预警级别='编入下一年级'
			where current of score_cursor

		fetch next from score_cursor into @累计学分,@预警级别
	end
close score_cursor
deallocate score_cursor

实验8.1 创建索引

实验八-1 创建索引

假设在teaching数据库应用中存在如下查询语句,请根据实际需要为该数据库表创建索引。

score(studentno,courseno,usually,finally) student(studentno,sname,sex,birthday,classno,point,phone,Email)

teach_class(teacherno,classno,courseno)

设置索引时,根据字段的实际读写频率设置其填充因子。

if exists(select name from sysindexes where name = 'IDX_sc')
	drop index student.sc
go
create index IDX_sc on student(studentno, classno)

–在score表的studentno和courseno列上建立一个复合索引sc_index

create index sc_index on score(studentno,courseno)

–在teach_class表的teacherno和courseno列上建立一个复合索引tc_index

create index tc_index on teach_class(teacherno,courseno)

(1)查询选修课程且期末成绩不为空的学生人数。

select (select COUNT(final) from score )

(2)查询所有Email使用126邮箱的学生的学号、姓名和电子邮箱地址。

select studentno,sname,email 
from student 
where email like'%@126%'

(3)查询每名学生的学号、选修课程数目、总成绩,并将查询结果存放到生成的“学生选课统计表”中。

select studentno,SUM(final) as 总成绩,COUNT(*) as 选课门数 into 学生选课统计表中 
from score 
group by studentno
select * from 学生选课统计表中

(4)查询选修’c05109’课程,并且期末成绩在前5名的学生学号、课程号和期末成绩。

select top 5 studentno,courseno,final 
from score 
where courseno='c05109' 
order by final desc

(5)查询教授两门及以上课程的教师编号、课程编号和任课班级。

select teacherno,classno,courseno 
from teach_class  
group by teacherno 
having COUNT(courseno)>=2 

(4)查询课程编号以’c05’开头,被三名及以上学生选修,且期末成绩的平均分高于75分的课程号、选修人数和期末成绩平均分,并按平均分的降序排序。

select courseno,COUNT(studentno) as 选修人数,AVG(final) as 平均分 
from score  
where courseno like'c05%'  
group by courseno 
having COUNT(*)>=3 

(7)查询所有17级学生的期末成绩平均分,要求利用COMPUTE BY方法显示每一名学生的学生编号、课程号、期末成绩的明细表,以及期末成绩平均分的汇总表。

select studentno 学生编号,courseno 课程号,final 期末成绩, avg(final) 平均分
from score
where studentno like '%17'
compute avg(final)

实验8.2 视图的建立

实验八-2 视图的建立

1.创建一个视图v_avgstu,查询每个学生的学号、姓名及平均分,并且按照平均分降序排序。

create view v_avgstu
as select top(100) percent student.studentno, student.sname, avg(score.final) average
from student, score
where student.studentno = score.studentno and score.final is not null
group by student.studentno, student.sname
order by avg(score.final) desc
go
select * from v_avgstu

2.修改v_teacher的视图定义,添加WITH CHECK OPTION选项。

alter view v_teacher
as select *
from teacher
with check option

3.通过视图v_teacher向基本表teacher中分别插入数据(‘05039’, ‘张馨月’, ‘计算机应用’, ‘讲师’, ‘计算机学院’)和(‘06018’, ‘李诚’, ‘机械制造’, ‘副教授’, ‘机械学院’),并查看插入数据情况。

insert into v_teacher values('05039','张馨月','计算机应用','讲师','计算机学院')
insert into v_teacher values('06018','李诚','机械制造','副教授','机械学院')
go
select * from v_teacher
select * from teacher

4.通过视图v_teacher将基本表teacher中教师编号为’05039’的教师职称修改为’副教授’

update v_teacher
set prof = '副教授'
where teacherno = '05039'
go
select * from teacher

5.建立试图v_score,查询每名学生的学号、性别和年龄,并在年龄字段上建立非聚集索引index_age

create index index_age on student(birthday)
go

create view v_score
as
select studentno, sex, birthday
from student
go

实验9.1 存储过程

实验九-1存储过程
(1)创建一个名称为StuInfo的存储过程,要求完成以下功能:在student表中查询17级学生的学号、姓名、性别、出生日期和电话个字段的内容

if exists (select name from sysobjects
where name='StuInfo'and type='p')
drop procedure StuInfo
go
create procedure StuInfo
as
select studentno,sname,sex,birthday,phone
from student
where substring(studentno,1,2)='17'

(2) 创建一个存储过程ScoreInfo,完成的功能是在表student、表course和表score中查询以下字段:学号、姓名、性别、课程名称、期末分数。

if exists(select name from sysobjects
where name='ScoreInfo'and type='p')
drop procedure ScoreInfo
go
create procedure ScoreInfo
as
select student.studentno,student.sname,student.sex,course.cname,score.final from student,course,score
where student.studentno=score.studentno and score.courseno=course.courseno
go

(3)创建一个名称为Student_Info1的存储过程,要求查询某位同学指定课程的成绩和学分。该存储过程接受与传递参数精确匹配的值。

if exists(select name from sysobjects
where name='Student_Info1'and type='p')
drop procedure Student_Info
go
create procedure Student_Info
@course nchar(8)
as
select course.period,credit from course
where course.cname=@course

(4)利用Transact-SQL语句创建一个带有参数的存储过程ProcInsert,向score表插入一条由参数指定的选课记录(学号、课程号、平时成绩、期末成绩),并查询该学生的姓名、选修的所有课程名称、平时成绩和期末成绩。

if exists(select name from sysobjects
where name='ProcInset'and type='p')
drop procedure ProcInset
go
create procedure ProcInset(
	@studentno nchar(11),
	@courseno nchar(6),
	@usully numeric(6,2),
	@final numeric(6,2))
as
insert into score values(@studentno,@courseno,@usully,@final)
select sname,cname,usually,final
from student,score,course
where student.studentno = score.studentno and student.studentno = @studentno and score.courseno= course.courseno

(5)统计输入课程的成绩分布情况,即按照各分数段来统计人数;
Rank( division CHAR(20), number INT )
division:‘[0,60)’ , ‘[60,80)’, ‘[80,100]’

CREATE TABLE Rank(
    division char(20),
    sub_sum int
)
INSERT INTO Rank(division)
VALUES('[0,60)'),('[60,70)'),('[70,80)'),('[80,90)'),('[90,100]');
CREATE PROCEDURE printcourse @pcname char(20)
AS
    DECLARE @pcno char(20),@pcount int
    UPDATE Course SET Cname=@pcname WHERE Cname=@pcname
    IF(@@ROWCOUNT=0)
         BEGIN
             RAISERROR('您输入的课程号不存在,请重新输入!', 16, 1)
             RETURN
         END
    SELECT @pcount=COUNT(*) FROM score WHERE final<60 

    UPDATE Rank SET sub_sum=@pcount WHERE division='[0,60)'
    SELECT @pcount=COUNT(*) FROM score WHERE final>=60 AND final<70 
    UPDATE Rank SET sub_sum=@pcount WHERE division='[60,70)'
    SELECT @pcount=COUNT(*) FROM score WHERE final>=70 AND final<80
    UPDATE Rank SET sub_sum=@pcount WHERE division='[70,80)'
    SELECT @pcount=COUNT(*) FROM score WHERE final>=80 AND final<90 
    UPDATE Rank SET sub_sum=@pcount WHERE division='[80,90)'
    SELECT @pcount=COUNT(*) FROM score WHERE final>=90 AND final<=100 
    UPDATE Rank SET sub_sum=@pcount WHERE division='[90,100]'
EXEC printcourse '数据库'
SELECT * FROM Rank

实验9.2 触发器

实验九-2 触发器

(1)创建AFTER触发器:在score表上创建一个插入、更新类型的触发器TR_ScoreCheck,当在score字段中插入或修改考试分数后,触发该触发器,检查分数是否在0-100之间。

if exists(select name from sysobjects where name = 'TR_ScoreCheck' and type = 'TR')
drop trigger TR_ScoreCheck
go
create trigger TR_ScoreCheck on score
for insert, update
as
if update(final) print 'AFTER触发器开始执行……'
begin
	declare @score real
	select @score = (select final from inserted)
	if @score >= 100 or @score < 0
	print '输入的分数有误,请确认输入的考试分数!'
end
go

(2)创建INSTEAD OF触发器:在course表上创建一个删除类型的触发器TR_NotAllowDelete,当在course表中删除记录时,触发该触发器,显示不允许删除表中数据的提示信息。

if exists(select name from sysobjects where name = 'TR_NotAllowDelete' and type = 'TR')
drop trigger TR_NotAllowDelete
go

create trigger TR_NotAllowDelete on course
after delete
as
print '本表中的数据不允许被删除'
rollback
go

(3)为student表创建一个名为“tri_de_s”的后触发器,当删除某条记录时,自动检查表score中是否有该学生的选课记录,如果存在则取消删除操作。

if exists(select name from sysobjects where name = 'tri_de_s' and type = 'TR')
drop trigger tri_de_s
go

create trigger tri_de_s on student
for delete
as
begin
	declare @sno char(10)
	select @sno = deleted.studentno from deleted
	if exists(select studentno from score where studentno = @sno)
	begin
		print 'score存在记录,禁止删除'
		rollback tran
	end
end

(4)为teacher 表创建触发器,保证教授工资不能低于4000元。
teacher(eno, job,sal)

if exists(select name from sysobjects where name = 'TR_SalCheck' and type = 'TR')
drop trigger TR_SalCheck
go

create trigger TR_SalCheck on teacher
for insert,update
as
begin
	declare @s numeric
	select @s = (select sal from inserted)
	if(@s < 4000)
	begin
		print '教授工资不能低于4000元'
		rollback
	end
end

实验9.3 存储过程附加

实验10 事务定义

事物定义
(1)定义一个事务Insert_XXXXX(用学号命名),在teaching数据库的student表和score表中新增一名学生的基本信息记录和选课记录,并提交该事务。通过查询语句验证插入语句是否成功。

(2)定义一个事务Insert_score,在teaching数据库向score表中增加学号为’16122221326’学生的选课记录,并回滚该事务。通过查询语句验证插入语句是否成功。
数据库应用与开发【实验题汇总】_第25张图片

(3)定义一个事务,将student表中学号为’16122221326’的学生性别修改为’女’,并设置一个保存点,然后将score表中学号为’16122221326’的学生期末成绩修改,最后回滚到事务的保存点,提交事务。通过查询语句验证修改语句是否成功。

(4)下面程序使用嵌套事务完成对score表的操作,在查询编辑器中输入如下程序并执行,并对执行过程和执行结果进行分析和解释。

USE teaching
GO
BEGIN TRAN outer_trans
  BEGIN TRAN inner_trans
    SELECT * FROM score WHERE studentno = '16122221326';
    UPDATE score
    SET final=95
    WHERE studentno = '16122221326';
    SELECT * FROM score WHERE studentno = '16122221326';
  COMMIT TRAN inner_trans;  
  UPDATE score
  SET usually=90
  WHERE studentno = '16122221326';
  SELECT * FROM score WHERE studentno = '16122221326';
ROLLBACK TRAN  outer_trans;  
SELECT * FROM score WHERE studentno = '16122221326';

如果提交外部事务,也将提交内部嵌套事务,如果回滚外部事物,也将回滚所有内部事务。

实验11 锁

实验十一 锁

  1. 设置隔离级别为read committed(缺省)方式,体会两个事务的并发执行结果。

(1) 打开第一个查询窗口,新建一个事务T1,更新student表的数据,如下:

begin transaction T1

update student set classno='1010' where studentno='16122221326'

(2) 打开第二个查询窗口,新建一个事务T2,查询student表的数据,如下:

begin transaction T2

select * from student

(3)观察发生的现象,查询语句可以执行吗,是否可以读到没有提交的事务?

不能执行事务T2中的查询语句

(4)在第一个查询窗口中,提交事务T1,然后观察查询语句是否执行了吗?

能执行事务T2中的查询语句,并且读取到了T1提交的事务


(5)加锁和解锁的操作是数据库用户吗?

不是,操作的是事务

(6) 在第二个查询窗口中,提交事务T2

  1. 设置隔离级别为read committed(缺省)方式,体会两个事务的并发执行结果。

(1) 打开第一个查询窗口,新建一个事务T1,查询student表的数据,如下:

begin transaction T1 

select * from student

(2) 打开第二个查询窗口,新建一个事务T2,更新student表的数据,如下:

begin transaction T2

update student set classno='1010' where studentno='16122221326'

commit transaction T2

(3)观察发生的现象,更新语句可以执行吗,是否可以修改正在被其他事务读取的数据?

可以
数据库应用与开发【实验题汇总】_第26张图片

(4)在第一个查询窗口中,再次执行查询语句select * from student,是否可以重复读?

(5) 在第一个查询窗口中,提交事务T1
数据库应用与开发【实验题汇总】_第27张图片

  1. 设置隔离级别为read uncommitted方式,体会两个事务的并发执行结果。

(1) 打开第一个查询窗口,新建一个事务T1,更新student表的数据,如下:

    begin transaction T1

update student set classno='1010' where studentno='16122221326'

(2) 打开第二个查询窗口,新建一个事务T2,查询student表的数据,如下:

begin transaction T2

select * from student

(3)观察发生的现象,查询语句可以执行吗,是否可以读到没有提交的事务?

可以执行查询语句,但是不能读取到没有提交的事务

(4)在第一个查询窗口中,回滚事务T1,T2事务的查询发生了什么问题?
没有出现问题

(5) 在第二个查询窗口中,提交事务T2

  1. 设置隔离级别为read committed(缺省)方式,体会两个事务的并发执行结果。

(1) 打开第一个查询窗口,新建一个事务T1,更新student表的数据,如下:

begin transaction T1

update student set classno='1010' where studentno='16122221326'

(2) 打开第二个查询窗口,新建一个事务T2,更新score表的数据,如下:

begin transaction T2

update score set usual=usual+10

(3) 在第一个查询窗口,执行语句

update score set final=final+5

观察发生的现象,语句update score set final=final+5可以执行吗?

不可以执行

(4) 在第二个查询窗口中,执行语句

update student set point=point+1

观察发生的现象,语句update student set point=point+1可以执行吗?
可以执行

(5)在成功执行的窗口输入commit语句并执行

实验13 SQL server安全管理

你可能感兴趣的:(数据库,sql)