上机练习4 一.实验目的 1. 熟悉和掌握对数据表中视图的查询操作和 SQL 命令的使用; 2. 熟悉和掌握对数据表中视图的更新操作和 SQL 命令的使用,并注意视图更新与基本表更新的区别与联系; 3. 学习灵活熟练的进行视图的操作,认识视图的作用。 二.实验内容 (一) 定义视图 以 Student, Course 和SC表为基础完成以下视图定义: 1. 定义信息系学生基本情况视图 V_IS; CREATE VIEW V_IS AS SELECT * FROM Student WHERE Sdept='信息系'; 2. 将 Student,Course 和 SC表中学生的学号,姓名,课程号,课程名,成绩定义为视图 V_S_C_G; CREATE VIEW V_S_C_G AS SELECT Student.Sno,Student.Sname,Course.Cno,Course.Cname ,Cscore FROM Student,Course,Score WHERE Student.Sno=Score.Sno AND Course.Cno = Score.Cno; 3. 将各系学生人数,平均年龄定义为视图 V_NUM_AVG; CREATE VIEW V_NUM_AVG(A_num,A_age) AS SELECT COUNT(*),AVG(YEAR(GETDATE())-DATENAME(yyyy,Sbirth)) FROM Student GROUP BY Sdept; 4. 定义一个反映学生出生年份的视图 V_YEAR; CREATE VIEW V_YEAR(Birth_year) AS SELECT DATENAME(yyyy,Sbirth) FROM Student; 5. 将各位学生选修课程的门数及平均成绩定义为视图 V_AVG_S_G; CREATE VIEW V_AVG_S_G(Num_of_course,A_grade) AS SELECT COUNT(*),AVG(Cscore) FROM Score GROUP BY Sno; 6. 将各门课程的选修人数及平均成绩定义为视图 V_AVG_C_G; CREATE VIEW V_AVG_C_G(Num_of_student,A_grade) AS SELECT COUNT(*),AVG(Cscore) FROM Score GROUP BY Cno; 7. 将各位学生学号、姓名,已选修课程的学分及其已取得的绩点定义为视图V_S_GPA CREATE VIEW V_S_GPA(Sno,Sname,Credit,gpa) AS SELECT Student.Sno,Sname,Ccredit, (CASE WHEN Cscore BETWEEN 90 AND 100 THEN 4.0 WHEN Cscore BETWEEN 85 AND 89 THEN 3.7 WHEN Cscore BETWEEN 82 AND 84 THEN 3.3 WHEN Cscore BETWEEN 78 AND 81 THEN 3.0 WHEN Cscore BETWEEN 75 AND 77 THEN 2.7 WHEN Cscore BETWEEN 71 AND 74 THEN 2.3 WHEN Cscore BETWEEN 66 AND 70 THEN 2.0 WHEN Cscore BETWEEN 62 AND 75 THEN 1.7 WHEN Cscore BETWEEN 60 AND 61 THEN 1.3 WHEN Cscore = 60 THEN 1.0 WHEN Cscore < 60 THEN 0 END) FROM Student,Course,Score WHERE Student.Sno=Score.Sno AND Course.Cno=Score.Cno; 现已知成绩绩点的计算方式如下: 成绩 等级 绩点 90-100 A 4.0 85-89 A- 3.7 82-84 B+ 3.3 78-81 B 3.0 75-77 B- 2.7 71-74 C+ 2.3 66-70 C 2.0 62-65 C- 1.7 60-61 D 1.3 补考60 D- 1.0 60以下 F 0 (二)使用视图 1. 查询以上所建的视图结果; SELECT * FROM V_AVG_C_G; SELECT * FROM V_AVG_S_G; SELECT * FROM V_IS; SELECT * FROM V_NUM_AVG; SELECT * FROM V_S_C_G; SELECT * FROM V_S_GPA; SELECT * FROM V_YEAR; 2.查询平均成绩为 90 分以上的学生学号、姓名和成绩; SELECT Sno,Sname,Cscore FROM V_S_C_G WHERE Sno IN (SELECT Sno FROM V_S_C_G GROUP BY Sno HAVING AVG(Cscore)>=90); 3. 查询各课成绩均大于平均成绩的学生学号、姓名、课程和成绩; SELECT * FROM V_S_C_G WHERE Sno IN (SELECT A.Sno FROM V_S_C_G A WHERE NOT EXISTS (SELECT B.Cscore FROM V_S_C_G B WHERE Cscore <= (SELECT AVG(C.Cscore)FROM V_S_C_G C WHERE B.Cno=C.cno) AND A.Sno=B.Sno ) ); 4.按系统计各系平均成绩在 80 分以上的人数,结果按降序排列;
SELECT COUNT(*),Sdept FROM Student WHERE Sno IN (SELECT V_S_C_G.Sno FROM V_S_C_G GROUP BY V_S_C_G.Sno HAVING AVG(Cscore)>=80) GROUP BY Sdept
SELECT Sdept,COUNT(A_grade) Num FROM Student,V_AVG_S_G WHERE Student.Sno=V_AVG_S_G.Sno AND A_grade>=80 GROUP BY Sdept ORDER BY Num desc;
5.查询平均绩点在 3.5 分以上的学生信息,结果按系排列显示。 (平均绩点(GPA)是国际通用的学生学习质量评定标准,其计算公式如下:课程学分1*绩点+课程学分2*绩点+......+课程学分n*绩点)/(课程学分1+课程学分2+......+课程学分n。) SELECT * FROM Student WHERE Sno IN ( SELECT Sno FROM V_S_GPA GROUP BY Sno HAVING SUM(Credit*gpa)/SUM(Credit)>3.5 ) ORDER BY Sdept; (三)修改视图 1. 通过视图V_IS,分别将学号为“0001”和“0004”的学生姓名更改为“刘二平”和“马西”,并查询结果; UPDATE V_IS SET Sname='刘二平' WHERE Sno='0001'; UPDATE V_IS SET Sname='马西' WHERE Sno='0004'; SELECT * FROM V_IS; SELECT * FROM Student; 2. 通过视图 V_IS,新增加一个学生记录 ('1001','韩磊',“男”,19, '信息系'),并查询结果; INSERT INTO V_IS(Sno,Sname,Sgender,Sage,Sdept) VALUES('1001','韩磊','男',19, '信息系'); SELECT * FROM V_IS WHERE Sno='1001'; SELECT * FROM Student WHERE Sno='1001'; 3. 通过视图 V_IS,新增加一个学生记录 ('1002','王超',“女”,19, 'FE'),并查询结果; INSERT INTO V_IS(Sno,Sname,Sgender,Sage,Sdept) VALUES('1002','王超','女',19, 'FE'); SELECT * FROM Student WHERE Sno='1002'; 4. 通过视图 V_IS,删除学号为“0016”和“0003”的学生信息,并查询结果; DELETE FROM V_IS WHERE Sno='0016' OR Sno='0003'; SELECT * FROM V_IS; SELECT * FROM Student; 5. 要通过视图V_S_C_G,将学号为“S12”的姓名改为“S12_MMM”,是否可以实现?并说明原因; UPDATE V_S_C_G SET Sname='S12_MMM' WHERE Sno='S12'; 可以实现。按理,由于V_S_C_G视图是由两个以上基本表导出的,则此视图不允许更新,但有时候也不一定。 6. 要通过视图V_AVG_S_G,将学号为“S1”的平均成绩改为90分,是否可以实现?并说明原因。 UPDATE V_AVG_S_G SET A_grade='90' WHERE Sno='S1'; 不能实现。因为V_AVG_S_G视图的字段来自聚集函数,含有GROUP BY字句,此视图不允许更新。 消息4406,级别16,状态1,第1 行 对视图或函数'V_AVG_S_G' 的更新或插入失败,因其包含派生域或常量域。