数据库原理与技术实验报告
课程名称:数据库原理与技术
实验报告要求:
1. 列出所有的SQL语句和源代码;
2. 程序要求有适当的注释;
3. 对数据完整性约束实施、实验三、实验四和实验五要求给出相应的测试用例。
4. 实验报告提交电子档。
实验内容:
实验一:创建表、更新表和实施数据完整性
1. 运行给定的SQL Script,建立数据库GlobalToyz。
2. 在企业管理器中建立所有表的关系图。
3. 利用系统定义的存储过程sp_helpdb查看数据库的相关信息,例如所有者、大小、创建日期等。
4. 列出所有表中出现的约束(包括Primary key, Foreign key, check constraint, default, unique)exec sp_helpconstraint Category
如此类推
5. 对Recipient表和Country表中的cCountryId属性定义一个用户自定义数据类型,并将该属性的类型定义为这个自定义数据类型。
exec sp_addtype hqok,'char(3)','null'
然后在企业管理器中打开该表,并对该类型进行重定义
6. 把价格在$20以上的所有玩具的信息拷贝到称为PremiumToys的新表中。
create table PremiumToys
(
cToyId char(6) check(cToyId like('[0-9][0-9][0-9][0-9][0-9][0-9]') )
constraint tt_id primary key clustered,
vToyName varchar(20) not null,
vToyDescription varchar(250),
cCategoryId char(3) references Category(cCategoryId) ,
mToyRate money not null,
cBrandId char(3)references ToyBrand(cBrandId),
imPhoto image,
siToyQoh smallint not null,
siLowerAge smallint not null,
siUpperAge smallint not null,
siToyWeight smallint,
vToyImgPath varchar(50) null
)
insert into PremiumToys select * from Toys where mToyRate > 20
7. 对表Toys实施下面数据完整性规则:(1)玩具的现有数量应在0到200之间;(2)玩具适宜的最低年龄缺省为1。
ALTER TABLE Toys
ADD CONSTRAINT siToyQoh_size check (siToyQoh>0 and siToyQoh <200)
ALTER TABLE Toys
ADD CONSTRAINT newsiLowerAge_min check (siLowerAge>=1)
8. 不修改已创建的Toys表,利用规则实现以下数据完整性:(1)玩具的价格应大于0;(2)玩具的重量应缺省为1
CREATE RULE mToyRate_min
AS @mToyRate > 0
sp_bindrule 'mToyRate_min','Toys.mToyRate'
CREATE RULE siToyWeight_init
AS @siToyWeight = 0
Sp_bindrule ‘siToyWeight_init’,’Toys.siToyWeight’
9. 给id为‘000001’玩具的价格增加$1。
update Toys set mToyRate=1+mToyRate where cToyId='000001'
10. 列出表PickofMonth中的所有记录,并显示中文列标题。
select cToyId as '玩具 id',siMonth as '出厂月份',iYear as '出厂年份', iTotalSold as '出厂总数' from PickOfMonth
实验二:查询数据库
1. 显示属于California和Illinoi州的顾客的名、姓和emailID。
select vFirstName,vLastName,vEmailId
from Shopper
where cState='California' or cState='Illinoi'
2. 显示定单号码、商店ID,定单的总价值,并以定单的总价值的升序排列。
select cOrderNo,cCartId,mTotalCost
from Orders order by mTotalCost
3. 显示在orderDetail表中vMessage为空值的。
select * from OrderDetail where vMessage is null
4. 显示玩具名字中有“Racer”字样的所有玩具的材料。
select vToyDescription
from Toys
where vToyName like '%Racer%'
5. 根据2000年的玩具销售总数,显示“Pick of the Month”玩具的前五名玩具的ID。
select top 5 CToyId
from PickOfMonth
where iYear=’2000’ order by iTotalSold
6. 根据OrderDetail表,显示玩具总价值大于¥50的定单的号码和玩具总价值。
Select cOrderNO,mToyCost
from OrderDetail
where mToyCost > 50
7. 显示一份包含所有装运信息的报表,包括:Order Number, Shipment Date, Actual Delivery Date, Days in Transit. (提示:Days in Transit = Actual Delivery Date – Shipment Date)
select OrderNO,dShipmentDate,dActualDeliveryDate,DaysinTransit=datediff(day,dShipmentDate,dActualDeliveryDate)
from Shipment
8. 显示所有玩具的名称、商标和种类(Toy Name, Brand, Category)。
select vToyName,cCategory,cBrandName
from Toys ,Category ,ToyBrand
where Toys.cCategoryId=Category.cCategoryId and Toys.cBrandId=ToyBrand.cBrandId
9. 以下列格式显示所有购物者的名字和他们的简称:(Initials, vFirstName, vLastName),例如Angela Smith的Initials为A.S。
select
vFirstName,vLastName,Substring(vFirstName,1,1)+'.'+Substring(vLastName,1,1) as Initials
from Shopper
10. 显示所有玩具的平均价格,并舍入到整数。
select round(avg(mToyRate),0) as AvgRate from Toys
11. 显示所有购买者和收货人的名、姓、地址和所在城市,要求显示结果集中的重复记录。
Select
a.vFirstName,a.vLastName,a.vAddress,a.cCity,b.vFirstName,b.vLastName,b.vAddress,b.cCity
from Shopper a,Recipient b,Orders c
where a.cShopperId=c.cShopperId a.and b.cOrderNO=c.cOrderNO
12. 显示没有包装的所有玩具的名称。(要求用子查询实现)
select vToyName
from Toys
where cToyId
in (select cToyId from OrderDetail
where cWrapperId is NULL)
13. 显示已发货定单的定单号码以及下定单的时间。(要求用子查询实现)
select cOrderNo,dOrderDate
from Orders where cOrderNo
in (select cOrderNo from Shipment
where dActualDeliveryDate is NOT NULL)
14. 显示一份基于Orderdetail的报表,包括cOrderNo,cToyId和mToyCost,记录以cOrderNo升序排列,并计算每一笔定单的玩具总价值。(提示:使用运算符COMPUTE BY)。
select cOrderNo,cToyId,mToyCost
from Orderdetail
order by cOrderNo
compute sum(mToyCost) by cOrderNo
实验三:视图与触发器
1. 定义一个视图,包括购买者的姓名、所在州和他们所订购玩具的名称、价格和数量。
create view ShopperandToys (vFirstName,vLastName,cState,vToyName,mToyRate,siQty)
as select a.vFirstName,a.vLastName,a.cState,b.vToyName,b.mToyRate,c.siQty
from Shopper a,Toys b,OrderDetail c,Orders d
where (a.cShopperId=d.cShopperId and b.cToyId=c.cToyId) and c.cOrderNo=d.cOrderNo
结果:
2. 基于(1)中定义的视图,查询显示所有California州的购买者的姓名和他们所订购玩具的名称及数量。
select vFirstName,vLastName,vToyName,siQty
from ShopperandToys
where cState='California'
视图定义如下:
CREATE VIEW vwOrderWrapper
AS
SELECT cOrderNo, cToyId, siQty, vDescription, mWrapperRate
FROM OrderDetail JOIN Wrapper
ON OrderDetail.cWrapperId = Wrapper.cWrapperId
以下更新命令,在更新siQty和mWrapperRate属性使用了以下更新命令时出现错误:
UPDATE vwOrderWrapper
SET siQty = 2, mWrapperRate = mWrapperRate + 1
FROM vwOrderWrapper
WHERE cOrderNo = ‘000001’
修改更新命令,以更新基表中的值。
UPDATE OrderDetail
SET siQty = 2
WHERE cOrderNo = '000001'
UPDATE Wrapper
SET mWrapperRate = mWrapperRate + 1
FROM OrderDetail a,Wrapper b
WHERE a.cOrderNo='000001' and a.cWrapperId=b.cWrapperId
3. 在OrderDetail上定义一个触发器,如果购物者改变了定单的数量,玩具的成本也自动地改变。(提示:Toy cost = Quantity * Toy Rate)
create trigger CheckToyCost
on OrderDetail
for update
as
if update(siQty)
begin
update OrderDetail
set mToyCost=siQty*mToyRate
f rom OrderDetail,Toys
end
go
测试用例:
对定单的数量修改前的OrderDetail:
对定单的数量进行修改:
修改后为:
4. 在(2)中定义的视图vwOrderWrapper上创建一个INSTEAD OF UPDATE触发器,以解决(2)中对视图进行更新时出现的问题。
实验四:存储过程
1. 编写一段程序,将每种玩具的价格提高¥0.5,直到玩具的平均价格接近$24.5为止。此外,任何玩具的最大价格不应超过$53。
程序为:
use GlobalToyz
go
while (select avg(mToyRate) from Toys)<24.5
begin
if (select max(mToyRate) from Toys)>53
begin
break
end
update Toys
set mToyRate=mToyRate+0.5
end
程序执行前:
程序执行后:
2. 创建一个称为prcCharges的存储过程,它返回某个定单号的装运费用和包装费用。
创建存储过程的语句为:
create proc prcCharges @OrderNo char(6) output
as
select cOrderNo,mShippingCharges,mGiftWrapCharges
from Orders
where cOrderNo=@OrderNo
go
测试:
打开所创建的存储过程,输入想要查找的订单号
执行后的结果为:
使用另外一种测试方法:
3. 创建一个称为prcHandlingCharges的过程,它接收定单号并显示经营费用。PrchandlingCharges过程应使用prcCharges过程来得到装运费和礼品包装费。
提示:经营费用=装运费+礼品包装费
创建存储过程的语句为:
create proc prcHandingCharges @OrderNo char(6)
as
create table #temp1( OrderNo char(6), mSCharges money, mGCharges money)
insert into #temp1 exec prcCharges @OrderNo
select OrderNo,mSCharges+mGCharges as HandingCharges from #temp1
go
测试用列:
实验五:事务与游标
1. 名为prcGenOrder的存储过程产生存在于数据库中的定单号:
CREATE PROCEDURE prcGenOrder
@OrderNo char(6) OUTPUT
as
SELECT @OrderNo=Max(cOrderNo) FROM Orders
SELECT @OrderNo=
CASE
WHEN @OrderNo>=0 and @OrderNo<9 Then
‘00000’+Convert(char,@OrderNo+1)
WHEN @OrderNo>=9 and @OrderNo<99 Then
‘0000’+Convert(char,@OrderNo+1)
WHEN @OrderNo>=99 and @OrderNo<999 Then
‘000’+Convert(char,@OrderNo+1)
WHEN @OrderNo>=999 and @OrderNo<9999 Then
‘00’+Convert(char,@OrderNo+1)
WHEN @OrderNo>=9999 and @OrderNo<99999 Then
‘0’+Convert(char,@OrderNo+1)
WHEN @OrderNo>=99999 Then Convert(char,@OrderNo+1)
END
RETURN
当购物者确认定单时,应该出现下面的步骤:
(1)用上面的过程产生定单号。
(2)定单号,当前日期,购物车ID,和购物者ID应该加到Orders表中。
(3)定单号,玩具ID,和数量应加到OrderDetail表中。
(4)在OrderDetail表中更新玩具成本。(提示:Toy cost = Quantity * Toy Rate).
将上述步骤定义为一个事务。编写一个过程以购物车ID和购物者ID为参数,实现这个事务。
该过程编写如下:
create proc prcOrder @CartID char(6),@ShopperID char(6)
as
declare @OrderNo char(6),@OrderNo1 char (6),@ToyID char (6),@Qty char (6)
exec prcGenOrder @OrderNo output
SELECT @OrderNo1=isnull( CONVERT(nvarchar, @OrderNo), '
create table #temp1
(OrderNo char (6),CartId char (6),ShopperId char (6),OrderDate datetime)
insert into #temp1 (OrderNo,CartId,ShopperId,OrderDate)
values(@OrderNo1,@CartID,@ShopperID,getdate())
insert into Orders (cOrderNo,cCartId,cShopperId,dOrderDate)
select * from #temp1
select @ToyID=cToyId,@Qty=siQty from ShoppingCart
where cCartId=@CartID
insert into OrderDetail (cOrderNo,cToyId,siQty)
values(@OrderNo1,@ToyID,@Qty)
update OrderDetail
set mToyCost=siQty*mToyRate
from OrderDetail,Toys
go
测试前的Orders:
注意:订单号只是到000010
测试前的OrderDetail:
对该过程进行测试:
注意:输入ToyId和ShopperId都为:000001
执行后的结果为:
Orders表:
注意:订单号自动生成,为000011
OrderDetail表:
2. 编写一个程序显示每天的定单状态。如果当天的定单值总合大于170,则显示“High sales”,否则显示”Low sales”.报告中要求列出日期、定单状态和定单总价值。
程序为:
declare @TotalCost money
select Orders.dOrderDate,Orders.cOrderProcessed,sum(mToyCost) as TotalCost
from Orders,OrderDetail
where Orders.cOrderNo=OrderDetail.cOrderNo and Orders.dOrderDate=getdate()
group by Orders.dOrderDate,Orders.cOrderProcessed
select @TotalCost=sum(mTotalCost)
from Orders,OrderDetail
where Orders.cOrderNo=OrderDetail.cOrderNo and Orders.dOrderDate=getdate()
if @TotalCost > 170
print 'High Sales'
else
print 'Low Sales'