其他分享
首页 > 其他分享> > 2021-11-15 基于音乐商店NetMusicShop的复杂查询(二)

2021-11-15 基于音乐商店NetMusicShop的复杂查询(二)

作者:互联网

先声明:本博客仅为个人作业不为标准答案,且复杂查询思路很多不同思路写出来的代码也不同,我写的也有可能漏洞百出,仅能作为参考哈!

先列一下知识点:

(一)集合查询

(1)并操作

格式:

<查询块> UNION <查询块>

参加UNION操作的各结果表的列数必须相同,对应项的数据类型也必须相同

例子:查询选修了1024或1136课程的学生

SELECT Sno
FROM SC
WHERE Cno= '1024'
UNION
SELECT Sno
FROM SC
WHERE Cno= '1136'

(2)交操作

格式:

<查询块> INTERSECT <查询块>

参加INTERSECT操作的各结果表的列数必须相同,对应项的数据类型也必须相同

例子:查询同时选修了1024和1136课程的学生

SELECT Sno
FROM SC 
WHERE Cno= '1024'
INTERSECT
SELECT Sno
FROM SC 
WHERE Cno= '1136'

(3)差操作

格式:

<查询块> EXCEPT <查询块>

参加EXCEPT操作的各结果表的列数必须相同,对应项的数据类型也必须相同

例子:查询选修了1024但没有选修1136课程的学生

SELECT Sno
FROM SC 
WHERE Cno= '1024'
EXCEPT
SELECT Sno
FROM SC 
WHERE Cno= '1136'

(二)视图

视图是从一个或几个基本表(或视图)导出的表,视图中的数据改变基表的数据也会改变,基表中的数据发生变化,从视图中查询出的数据也随之改变

(1)定义格式:

CREATE VIEW <视图名>[(<列名>[, <列名>]...)] AS <子查询>

说明:

<子查询>可以是任意复杂的SELECT语句,但通常不允许含有ORDER BY子句和DISTINCT短语

(除非在SELECT子句中添加TOP n关键字)(这里在后面实例题中有更详细说明)

(2)视图的种类:

单表视图:一个基本表的行列子集

多表视图:多个基本表的行列子集

视图的视图:建立在一个或多个已定义好的视图上的视图

虚拟列视图:带表达式/计算视图

分组视图:含GROUP子句及聚集函数

(3)删除视图

格式:

DROP VIEW <视图名>

(4)视图的作用

1.视图能够简化用户的操作

2.视图使用户能以多种角度看待同一数据,适应数据库共享的需要

3.视图对重构数据库提供了一定程度的逻辑独立性

4.视图能够对机密数据提供安全保护,隐藏 了底层的表结构,用户只能看到视图提供的数据

5.适当的利用视图可以更清晰的表达查询

(三)数据更新

(1)批量插入数据

格式:

INSERT INTO <表名> (<属性列1> [, <属性列2>...] ) <子查询>

例子:每一个学生 都要选修 高等数学(1128)课,将选课信息加入表SC中

INSERT INTO SC(Sno, Cno)
SELECT Sno, '1128'
FROM Student

(2)批量修改数据

格式:

UPDATE <表名>
SET <列名>=<子查询> [,<列名>=<表达式> ]
[ WHERE <含子查询的条件> ]

例子:将计算机系全体学生的“数据库原理”成绩修改为空值

UPDATE SC
SET Grade = NULL
WHERE Cno IN
(SELECT Cno 
FROM Course
WHERE Cname='数据库原理')
AND Sno IN
(SELECT Sno 
FROM Student
WHERE Sdept = '计算机');

(3)批量删除数据

格式:

DELETE FROM <表名> [WHERE <含子查询的条件>] 

例子:删除计算机系所有学生的选课记录

DELETE FROM SC 
WHERE Sno IN
(SELECT Sno
FROM Student
WHERE Sdept='计算机');

之后记录题目:

1、商家开展“买200赠100”的促销活动,为一次购买某专辑总价格在200元(含)以上的用户的会员卡(字段:User表的UserAdvancePayment)充值100元。(只充值一次)

UPDATE users SET UserAdvancePayment=0;
UPDATE users SET UserAdvancePayment=UserAdvancePayment+100
WHERE UserName IN 
(SELECT UserName 
FROM sales,orders
WHERE sales.OrderID=orders.OrderID AND TotalPrice>=200);

2、新建“专辑销售统计表”Sales_Statis,其结构能存放专辑名、销售量和销售额。将各个专辑销售量和销售额的统计结果存入Sales_Statis表中

CREATE TABLE Sales_Statis(
AlbumName varchar(64) not null,
Quantity int null,
TotalPrice numeric(10, 2) null
);
INSERT INTO Sales_Statis
SELECT AlbumName,Quantity,TotalPrice
FROM albums,
(SELECT AlbumID,SUM(Quantity) AS Quantity,SUM(TotalPrice) AS TotalPrice 
FROM sales
GROUP BY AlbumID) AS s
WHERE albums.AlbumID=s.AlbumID;

3、创建专辑名为“三十而立”(可自定义其他名称)的歌曲视图SongsByAlbumName,该视图包括“歌曲表”中的所有列以及专辑名称,并按歌曲顺序号由小到大排列

4、将此视图中选择任意SongId,修改歌曲名称为“我就想改改名字看看能不能成功”,看看是否成功?

5、将此视图中选择任意SongId,修改歌曲名称为“我就想改改名字看看能不能成功”,专辑名称修改为“我还想改一下专辑试试”,看看是否成功?

6、对于视图是否能修改成功,相关的因素有哪些?请一一列举并举例说明,附上测试结果

CREATE VIEW SongsByAlbumName 
AS 
SELECT TOP 100 PERCENT songs.*,albums.AlbumName
FROM songs,albums 
WHERE songs.AlbumID=albums.AlbumID AND albums.AlbumName="三十而立"
ORDER BY songs.SongID ASC;

注意:select + order by 的组合返回的是游标而非table,直接select传给view再update的时候会报错Incorrect usage of UPDATE and ORDER BY,因而必须加上 top 100 percent转化成table,但是mysql不支持TOP语句,mysql中可以用LIMIT语句来代替,

格式为:

SELECT * FROM table  LIMIT [offset,] rows | rows OFFSET offset;

第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目,若值为5,10,则检索记录行6-15,但是LIMIT没法像TOP那样选中全部数据,只能设定一个比较大的区间,但LIMIT可以选择位于中间区段的数据,本题可以写为:

CREATE VIEW SongsByAlbumName 
AS 
SELECT songs.*,albums.AlbumName
FROM songs,albums 
WHERE songs.AlbumID=albums.AlbumID AND albums.AlbumName="三十而立"
ORDER BY songs.SongID ASC LIMIT 0,100;

但这样写会报错The target table SongsByAlbumName of the UPDATE is not updatable

当视图中包含有如下内容时,视图的更新操作将不能被执行:
(1)视图中不包含基表中被定义为非空的列
(2)在定义视图的SELECT语句后的字段列表中使用了数学表达式
(3)在定义视图的SELECT语句后的字段列表中使用聚合函数
(4)在定义视图的SELECT语句中使用了DISTINCT、UNION、TOP、GROUP BY、ORDER BY或HAVING子句

所以最好还是不要对视图进行排序了,题目也要求的是ASC,视图默认排列顺序也是ASC,直接这样写:

CREATE VIEW SongsByAlbumName 
AS 
SELECT songs.*,albums.AlbumName
FROM songs,albums 
WHERE songs.AlbumID=albums.AlbumID AND albums.AlbumName="三十而立";

如果想要查询倒序的视图,使用以下语句:

SELECT * FROM SongsByAlbumName ORDER BY SongID DESC;

按照以上语句写的就可以进行update了:

UPDATE SongsByAlbumName
SET SongTitle ="我就想改改名字看看能不能成功"
WHERE SongID=8;

当想要同时更改两个变量,如下所写:

UPDATE SongsByAlbumName
SET SongTitle ="我就想改改名字看看能不能成功",AlbumName="我还想改一下专辑试试"
WHERE SongID=6;

就会报错:Can not modify more than one base table through a join view 'songalbum.songsbyalbumname'

因此基表要分开一个个更新,如下所写:

UPDATE SongsByAlbumName
SET SongTitle ="我就想改改名字看看能不能成功"
WHERE SongID=8;
UPDATE SongsByAlbumName
SET AlbumName="我还想改一下专辑试试"
WHERE SongID=8;

这样就可以成功运行了,此时原表中的歌曲名和专辑名就会改变,视图表因为原表中专辑名改变会清空


本次记录就到这,下次见~

标签:11,15,Sno,视图,NetMusicShop,albums,WHERE,SELECT,songs
来源: https://blog.csdn.net/m0_52461904/article/details/121341728