设计性实验
1. 创建视图V_A包括学号,姓名,性别,课程号,课程名、成绩;
一个语句把学号103 课程号3-105 的姓名改为陆君茹1,性别为女 ,然后查看学生表的信息变化,再把上述数据改为原值
-- 创建视图 V_A_065
CREATE VIEW V_A_065 AS
SELECT s.Sno 学号, s.Sname 姓名, s.Ssex 性别, sc.Cno 课程号, c.Cname 课程名, sc.Degree 成绩
FROM student065 s
JOIN Score065 sc ON sc.Sno = s.Sno
JOIN Course065 c ON c.Cno = sc.Cno;-- 修改数据
UPDATE V_A_065
SET 姓名 = '陆君茹1', 性别 = '女'
WHERE 学号 = '103' AND 课程号 = '3-105';-- 还原
UPDATE V_A_065
SET 姓名 = '陆君茹', 性别 = '男'
WHERE 学号 = '103' AND 课程号 = '3-105';
-- 验证视图结构和数据
SELECT * FROM V_A_065;
一个语句把学号101 课程号4-101 的姓名改为李君帅1,课程名为[马克思主义基本原理]概论]?如何才能完成修改,再把上述数据改为原值
由于课程名是只读字段(来自 Course065 表),不能通过视图直接修改。
只能更新允许更新的字段(如学生姓名)
-- 只修改姓名
UPDATE V_A_065
SET 姓名 = '李君帅1'
WHERE 学号 = '101' AND 课程号 = '4-101';
查看修改后的视图数据 SELECT * FROM V_A_065 WHERE 学号 = '101' AND 课程号 = '4-101';
查看原始学生表是否更新 SELECT * FROM student065 WHERE Sno = '101';
– 添加一行数据 --视图涉及多张表连接,默认不允许直接插入。需创建 INSTEAD OF INSERT 触发器 或 直接插入基础表
向基础表中插入
INSERT INTO student065(Sno, Sname, Ssex, Sbirthday, Class)
VALUES ('110', '张小红', '女', NULL, NULL);INSERT INTO Course065(Cno, Cname, Tno)
VALUES ('C001', '高等数学', 'T001');INSERT INTO Score065(Sno, Cno, Degree)
VALUES ('110', 'C001', 88);
-- 查看新增记录是否出现在视图中
SELECT * FROM V_A_065 WHERE 学号 = '110';
2. 创建视图V_B, 优秀学生(所有成绩不低于80),包括姓名,课程名、成绩 (WITH ENCRYPTION)
检查WITH ENCRYPTION 效果
创建加密视图
CREATE VIEW V_B1_065 WITH ENCRYPTION AS
SELECT s.Sname 姓名, c.Cname 课程名, sc.Degree 成绩
FROM student065 s
JOIN Score065 sc ON sc.Sno = s.Sno
JOIN Course065 c ON c.Cno = sc.Cno
WHERE sc.Degree >= 80;
GO
-- 查看系统表中视图定义
SELECT name, text
FROM sysobjects o
JOIN syscomments c ON o.id = c.id
WHERE name = 'V_B1_065';--加密成功时,text 字段为空或乱码
把王丽娜 的计算机导论 成绩(91)改为80,并查看成绩表和V_B中的数据
修改成绩
UPDATE Score065
SET Degree = 80
WHERE Sno = '107' AND Cno = '3-105';
-- 查看视图中是否包含该记录
SELECT * FROM V_B1_065 WHERE 姓名 = '王丽娜' AND 课程名 = '计算机导论';
3.创建视图V_C, 优秀学生(所有成绩不低于80),包括姓名,课程名、成绩 (WITH check option)
检查WITH check option效果
把王丽娜的计算机导论 成绩(91)改为85,并查看成绩表和V_C中的数据
--创建带 CHECK OPTION 的视图
CREATE VIEW V_C1_065 AS
SELECT s.Sname 姓名, c.Cname 课程名, sc.Degree 成绩
FROM student065 s
JOIN Score065 sc ON sc.Sno = s.Sno
JOIN Course065 c ON c.Cno = sc.Cno
WHERE sc.Degree >= 80
WITH CHECK OPTION;
GO
-- 成功修改
UPDATE V_C1_065
SET 成绩 = 85
WHERE 姓名 = '王丽娜' AND 课程名 = '计算机导论';
-- 查看最终成绩
SELECT * FROM Score065 WHERE Sno = '107' AND Cno = '3-105';----再把王丽娜 的计算机导论 成绩改为78,并查看成绩表和V_C中的数据 ???
UPDATE V_C1_065
SET 成绩 = 78
WHERE 姓名 = '王丽娜' AND 课程名 = '计算机导论';
4.对教师表按姓名创建唯一性索引;
创建唯一索引
CREATE UNIQUE INDEX tname_UNI_ind_065 ON teacher065 (Tname);
查看索引信息
EXEC sp_helpindex 'teacher065';
5.对课程表按课程名创建聚集索引;???
– 创建聚集索引
CREATE CLUSTERED INDEX cname_cl_ind_065 ON Course065 (Cname);
– 查看索引信息
EXEC sp_helpindex ‘Course065’;
6.创建索引视图V_D,包括学号,姓名,性别,课程号,课程名、成绩,并按姓名创建索引
创建带 SCHEMABINDING 的视图
CREATE VIEW V_D_065 WITH SCHEMABINDING AS
SELECT s.Sno, s.Sname, s.Ssex, sc.Cno, c.Cname, sc.Degree
FROM dbo.student065 s
JOIN dbo.Score065 sc ON sc.Sno = s.Sno
JOIN dbo.Course065 c ON c.Cno = sc.Cno;
GO
-- 创建聚集索引
CREATE UNIQUE CLUSTERED INDEX sname_ind_065 ON V_D_065 (Sname);
-- 查看索引信息
EXEC sp_helpindex 'V_D_065';
7.删除上述建的全部索引
-- 删除索引
DROP INDEX IF EXISTS tname_UNI_ind_065 ON teacher065;
DROP INDEX IF EXISTS cname_cl_ind_065 ON Course065;
DROP INDEX IF EXISTS sname_ind_065 ON V_D_065;-- 查看剩余索引
EXEC sp_helpindex 'teacher065';
EXEC sp_helpindex 'Course065';
EXEC sp_helpindex 'V_D_065';
思考题
(1)视图的作用是什么?
简化复杂查询:视图可以将复杂的多表查询、连接等操作封装起来,提供一个简单的接口给用户。
提高安全性:通过视图限制用户只能访问特定的数据列或行,保护敏感数据不被未授权用户查看。
实现逻辑独立性:当底层数据库结构发生变化时(如表结构修改),如果应用使用的是视图而不是直接操作表,只需调整视图定义即可,不影响前端应用。
支持虚拟表操作:例如聚合、分组等操作可以直接在视图中定义,简化了数据分析过程。
(2)什么是索引视图?如何创建
索引视图:是指带有聚集索引的视图。与普通视图不同,索引视图的数据是物理存储的,这使得它能够显著提高查询性能,特别是对于那些频繁使用的复杂查询。
创建方法:
必须使用 WITH SCHEMABINDING 创建视图,以确保视图定义不会因为基础表结构的变化而失效。
(3)举例说明什么是聚集索引,非聚集索引
聚集索引(Clustered Index):决定了表中数据的物理存储顺序。每个表只能有一个聚集索引。例如,在学生表中按照学号(Sno)排序,则学号上的索引就是聚集索引。
CREATE CLUSTERED INDEX idx_student_Sno ON student065(Sno);
非聚集索引(Nonclustered Index):并不改变数据的实际存储顺序,而是创建一个包含指向实际数据页指针的索引结构。一张表可以有多个非聚集索引。例如,在学生表中按姓名(Sname)建立非聚集索引。
CREATE NONCLUSTERED INDEX idx_student_Sname ON student065(Sname);
(4)简述使用聚集索引,非聚集索引检索数据的过程?
聚集索引检索过程:当你根据聚集索引键(如学号)进行查询时,数据库可以直接定位到数据所在的位置,因为它反映了数据的实际存储顺序。
非聚集索引检索过程:首先查找非聚集索引找到对应记录的指针,然后根据这个指针再去读取实际的数据页。这意味着非聚集索引通常需要两次I/O操作(一次用于读取索引页,另一次用于读取数据页)。
(5)什么是全文索引?如何创建和使用?(有兴趣的同学选做)
全文索引(Full-Text Index):是一种特殊的索引类型,用于对文本类型字段(如VARCHAR, NVARCHAR, TEXT等)进行高效的搜索。它支持更高级的搜索功能,比如全文搜索、布尔运算符、近似词匹配等。
实验小结(实验中遇到的问题及解决过程、实验中产生的错误及原因分析、实验体会和收获)
在这次数据库实验中,我学习了视图和索引的功能及其应用,让我对数据库设计有了更深的理解。整个过程充满了挑战,但正是这些挑战促使我在解决问题的过程中不断进步。
创建视图时,我最初遇到了一些困惑,例如试图在一个批处理中同时执行 CREATE VIEW 和 SELECT * FROM view_name 的命令,结果系统提示错误信息:“不能在一个批处理中创建视图并查询它。”经过查阅资料和反复尝试,我发现每个DDL操作(如 CREATE, ALTER)必须单独作为一个批处理来执行,中间需要用 GO 分隔开。
在使用视图进行数据更新时,我又遭遇了新的问题。当试图通过多表连接的视图修改某些字段时,发现有些字段能够成功更新,而另一些则会失败。比如,修改学生姓名可以顺利完成,但尝试更改课程名称却无法实现。这是因为课程名称来源于另一张表,SQL Server不允许直接通过视图修改多个基表的数据。这个问题教会了我区分哪些字段是可更新的,如果确实需要修改,可以通过触发器(INSTEAD OF UPDATE)间接完成,或者直接操作基础表。
此外,我尝试向视图中插入新记录,却收到了“视图不可更新”的错误提示。这表明该视图涉及多张表的连接,SQL Server默认情况下不允许这样的操作。解决方法包括创建 INSTEAD OF INSERT 触发器,或直接操作基础表进行插入。
在为视图添加索引的过程中,我也遇到了不少困难,比如提示“不能为未绑定架构的视图创建索引”、“必须先创建聚集索引”等。原来,索引视图有着严格的限制条件。为了克服这些问题,我学会了使用 WITH SCHEMABINDING 创建视图,并确保所有引用的表和列都加上了 dbo. 前缀,同时还必须首先创建唯一的聚集索引,保证视图中没有聚合函数或复杂的表达式。通过这次实践,我对索引的本质和用途有了更加直观的认识,了解到正确的索引设计对于提升查询效率至关重要。
总的来说,这次实验不仅让我掌握了视图和索引的基本操作,更让我体会到数据库系统的强大功能与灵活性。虽然过程中遇到了许多障碍,但正是这些挑战帮助我在解决问题的同时不断提升自我。这次宝贵的经验将成为我未来学习道路上的重要财富,激励我继续探索数据库领域的更多奥秘,也希望自己可以花更多时间学习数据库。