【SQL Server】一次数据库练习——题目+思路+答案

 
 
 

E-R图

在这里插入图片描述
 
 

分析E-R图

先观察实体,一共有5个;5个实体分别对应5个表(table) —— Users, Songs, MusicCategory, Orders, Album

为了给实体(或者说表)建立联系,需要弄清楚外键应该做在哪里

外键做在哪,是根据数量关系决定的。1对多的关系(1:M),外键做在“多”对应的表中(属性就写在“多”对应的表中);

多对多的关系(M:N),则另需要建表,如此E-R图中,还需要Collections表和Sale
 
 

代码

建表过程已知,重点是题目

-- 实验一——PPT_1

-- 创建数据库
create database NetMusicShop

use NetMusicShop
go

-- 建表(用户表)
create table Users
(
	UserName			varchar(20),
	UserPassword		varchar(6),
	UserSex				char(2),
	UserRealName		varchar(20),
	UserAgeRange		char(8),
	UserAddress			varchar(256),
	UserPostCode		char(6),
	UserPhone			varchar(32),
	UserEmail			varchar(50),
	UserRegisterTime	smalldatetime,
	UserAdvancePayment	numeric(8,2)
)

-- 建表(专辑表)
create table Album
(
	AlbumID            tinyint identity(1, 1),
	AlbumName          varchar(64) not null,
	AlbumIssueCompany  varchar(64),
	AlbumIssueDate     smalldatetime,
	AlbumType          tinyint,
	AlbumIntroduce     varchar(4096),
	AlbumImageUrl      varchar(200),                     
	AlbumSinger        varchar(32), 
	AlbumLanguage      varchar(10),
	AlbumMarketPrice   numeric(6,2),
	AlbumMemberPrice   numeric(6,2),
	AlbumIsRecommend   bit
)

-- 数据表管理(考察列(属性)层面的操作:增、改、删) :

-- 向Users表增加“修改时间”列UserUpdateTime,其数据类型为短日期型
alter table Users
add UserUpdateTime smalldatetime

-- 将Users表的Usersex列的数据类型改为整数,1表示“男”,0表示“女”
alter table Users
alter column Usersex int

-- 删除Users表的UserUpdateTime列
alter table Users
drop column UserUpdateTime

-- 删除数据表Users(考察在table表层面的操作)
--drop table Users

-- 在User表的用户名列上建立一个名为Users_Name_Index的非聚集索引
create nonclustered index Users_Name_Index on Users(UserName)

-- 数据操纵(考察数据层面的操作:插入数据、修改数据、删除数据) :

-- 插入一行用户数据
insert into Users(UserName, UserPassword, UserSex, UserRealName, UserAgeRange, UserAddress, UserPostCode, UserPhone, UserEmail)
values('ws', '123','女','王珊','21-30岁','北京海淀区中关村','100098','18611983575','[email protected]')

-- 修改数据
-- 将用户名为ws的用户的密码改为111
update Users
set UserPassword = '1111' where UserName = 'ws'
-- 删除名为ws的用户数据
delete Users
where UserName = 'ws'




-- 实验二——PPT_2

-- 0.准备工作:

-- 0.1 设置Users表的UserPassword列不能为空(考察对约束的操作)
alter table Users
add constraint ct_tk check(UserPassword is not null)
-- 实际上添加的这个非空约束,是通过一个check约束间接实现的

-- 0.2 建立歌曲表Songs和Collections表
-- 我们来分析一下:
-- 首先,我们已经有了用户表Users和专辑表Album
-- 歌曲和专辑是多对1的关系,因此外键做在Songs表中
-- 用户和歌曲是多对多的关系,因此另外需要一个表(收藏表Collections),在收藏表中做外键

-- 下面建表:
-- Songs歌曲表
create table Songs
(
	SongID	tinyint identity PRIMARY KEY,
	SongNumber       tinyint,
	AlbumID  	     tinyint,
	SongTitle	     varchar(256) NOT NULL,
	SongDuration	 char(8),
	SongContent      varchar(4096),
	SongUploadDate	 smalldatetime ,
	SongUrl	         varchar(200),
	SongFormat       varchar(10),
	SongLanguage     varchar(10),
	SongType         tinyint,
	SongSinger	     varchar(32),		
	SongIsRecommend	 bit
)
-- Collections收藏表
create table Collections
(
	CollectionID tinyint identity PRIMARY KEY,
	SongID          tinyint,
	UserName        varchar(20),
	CollectionDate	smalldatetime
)

-- 1.数据查询 :

--(1)用中文标题显示所有专辑的专辑名称、发行公司、发行时间、专辑类别、专辑歌手信息,并按发行时间降序排序
select AlbumName as 专辑名称, AlbumIssueCompany 发行公司, AlbumIssueDate 发行时间, AlbumType 专辑类别, AlbumSinger 专辑歌手信息
from Album
order by AlbumIssueDate desc

--(2)查找专辑名称中包含“歌”且会员价格低于80的专辑,显示其全部信息
select *
from Album
where AlbumName like '%歌%' and AlbumMemberPrice < 80

--(3)查找收藏歌曲在2首以上的用户的及其收藏的歌曲数,显示中文标题
select UserName as 用户名,count(*) as 收藏数
from Collections
group by u.UserName having count(*) > 2
-- 分析:考察了分组、分组后筛选

--(3.1) 查找至少收藏了2首歌曲的用户(用连接查询实现)
select distinct x.UserName
from Collections x
inner join Collections y on x.UserName = y.UserName
where x.SongID != y.SongID
-- 分析:通过自连接实现(比较巧妙)
-- 也可以这样写 :
select distinct x.UserName
from Collections x, Collections y
where x.UserName = y.UserName and x.SongID != y.SongID

--(4)显示各公司发行的专辑最低和最高市场价格
select MAX(AlbumMarketPrice) as 最高市场价, MIN(AlbumMarketPrice) as 最低市场价
from Album
group by AlbumIssueCompany
-- 分析:聚合函数的使用,很简单

--(5)查找所包含的歌曲数大于等于10首的专辑,显示专辑名和包含的歌曲数
select AlbumName as 专辑名, count(*) as 歌曲数
from Album as a
inner join Songs as s on a.AlbumID = s.AlbumID
group by AlbumName having count(*) >= 10
-- 分析:考察是联合查询、分组、分组后筛选;这里再强调一遍这个规律:分组后可以写在select后面的,只能是分组依据和聚合函数



-- 实验三——PPT_3

-- 0.准备工作:新建Order订单表,Sale表,MusicCategory表
--分析:目前为止有了Users用户表,Album专辑表,Songs歌曲表,Collections收藏表,Orders订单表,Sale表

-- Orders订单表
create table Orders
(
	OrderID				tinyint IDENTITY primary key,
	OrderDate			smalldatetime NULL,
	UserName			varchar(20) null,
	GoodsFee			numeric(8,2) null,
	DeliverFee			numeric(8,2) null,
	DeliverID			tinyint null,
	AreaID				tinyint null,
	PaymentID			tinyint null,
	ReceiverName		varchar(20) null,
	ReceiverAddress		varchar(256) null,
	ReceiverPostCode	char(6) null,
	ReceiverPhone		varchar(32) null,
	ReceiverEmail		varchar(50) null,
	OrderIsPayment		bit null,
	OrderIsConsignment	bit null,
	OrderIsConfirm		bit null,
	OrderIsPigeonhole	bit null,
)

-- Sale表
create table Sale
(
	SaleID		tinyint identity primary key,
	OrderID		tinyint null,
	AlbumID		tinyint null,
	Quantity	tinyint null,
	TotalPrice	numeric(10, 2) null
)

-- MusicCategory表
create table MusicCategory
(
	CategoryID			tinyint identity primary key,
	CategoryName		varchar(20) not null,
	CategoryImageUrl	varchar(200) null
)


-- 1.实验内容(数据查询)

--(1)通过观察表数据及表结构,画出Users表、Album表、Songs表、Collections表、Orders表、Sale表、MusicCategory表的E-R图(反向工程)
-- E-R图见最上方

--(2)列出演唱流行歌曲的歌手名单(流行/Pop)
select distinct a.AlbumSinger as 流行歌手
from Album a, MusicCategory m
where a.AlbumType = m.CategoryID and CategoryName='流行/Pop' 

--(3)查找最近9年来的专辑销售情况,列出专辑ID、专辑名称、总销售额,按总销售额从高到低排名
select Album.AlbumID 专辑ID, Album.AlbumName 专辑名称, sum(Sale.TotalPrice) 总销售额
from Album, Sale, Orders	-- 专辑ID需要Album表,总销售额需要Order表,它们多对多的关系通过Sale表实现
where Sale.OrderID = Orders.OrderID and Sale.AlbumID = Album.AlbumID
and datediff(year, Orders.OrderDate, getdate()) <= 9
group by Album.AlbumID, Album.AlbumName		-- 这里的Album.AlbumName看似多余,实则是必需的——被select的列必须是分组依据和聚合函数
order by sum(Sale.TotalPrice)
-- 分析:依旧是经典的联合查询(三表连接);值得注意的是该题考察了日期时间相关的函数:时间差datediff
-- 复习:获取当前时间getdate(),时间差datediff,时间和dateadd,取时间的部分datepart
-- 典例用法:datediff(year, '2000-06-21', getdate());dateadd(day, 20, getdate()), datepart(year, getdate());

--(4)查询没有被收藏过的歌曲的全部信息
select *
from Songs
where SongID not in (select distinct s.SongID from Collections as c inner join Songs as s on c.SongID = s.SongID)
-- 分析:子查询
-- 另法:
select *
from Songs s
left outer join Collections c on s.SongID = c.SongID
where CollectionID is null
-- 分析:外连接

--(5)最后,将数据库备份一份,并尝试恢复是否成功,若没问题就带走

-- 备份方式1:分离附加——右键需要备份的数据库→分离;右键上级目录即“数据库”→附加
-- 或者:
exec sp_detach_db NetMusicshop

exec sp_attach_db @dbname = NetMusicshop, 
@filename1 = 'D:\SQL Server\NetMusicShop.mdf', 
@filename2 = 'D:\SQL Server\NetMusicShop.ldf' 

-- 备份方式2:备份与恢复数据库
exec sp_addumpdevice 'DISK', 'BP1', 'd:\SQL Server BP\NetMusicShop1.bak'
backup database NetMusicShop to BP1

restore database NetMusicShop
from BP1
with file=1, replace



猜你喜欢

转载自blog.csdn.net/m0_46202073/article/details/106299839