数据库系统原理,《实验指导书》
1 实验八:数据库完整性
1.1 实验背景
“存储在数据库中的所有数据值均是正确的状态。如果数据库中存储有不正确的数据值,则该数据库称为已丧失数据完整性。”
这是SQL Server2000中给出数据库完整性的解释,但是我们要问两个问题:
什么是数据正确的状态? 如何确保数据是正确的?
对于第一个问题,确实很难回答,因为:“世界上所有事物本无正确与错误”,但是一些不符合逻辑的、前后矛盾的、没有满足人们需求的,可以说是“不正确的”。如:一个人的年龄是“-20岁”,这就是不符合逻辑的;在一个地方,这个人叫“张三”,但是换了个地方却记成“张山”,这就是矛盾;如果一笔订单金额没有达到1万元,却给记成打了8折,实际只能打9折,这就是不满足需求。
造成上述各种不正确的原因是什么呢?无外乎是人们输入错误、业务不熟悉、或者是捣乱分子故意为之。那么关键问题是我们如何在数据库中预防这种不正确的情况呢?这就是要问的第二个问题。
这需要靠数据库管理系统(DBMS)提供一套完整性约束机制来预防这种情况的发生。但是人们常说一句话“人无完人,金无足赤”,同样,要完全靠DBMS帮我们防住所有的不正确,本身就是不正确的,这不符合辩证哲学的观点。这说明DBMS只能是尽可能的预防。那么人们要深入研究有哪些完整性约束,DBMS应该提供哪些保障机制。
首先,完整性约束主要有以下几种:
实体完整性约束 参照完整性约束 用户定义完整性约束
其次,在关系型数据库中保证上述完整性约束的方法有以下几种:
表 1 数据库提供的约束
数据库提供的约束 主码约束 外码约束 Check约束 Null约束 索引约束 触发器 存储过程 理论上的完整性约束 实体完整性约束 参照完整性约束 用户定义完整性约束 我们可以看出主码、外码是我们经常接触到的数据库提供的约束方法,也是最重要的约束。但是,外码约束并没有我们想象那样简单,即只要把外码关系建立起来就行了,还要考虑到约束强度的问题:
表 2参照完整性约束的类型与强度
数据库系统原理,《实验指导书》 参照完整性类型 不实施参照完整性约束 实施级联更新参照完整性约束 实施级联删除参照完整性约束 实施更新参照完整性约束 实施删除参照完整性约束 实施插入参照完整性约束 约束强度 强度为零 中等强度 中等强度 高强度 高强度 高强度 这种情况最好要避免。 可以实施。当主码修改了,外码自动被修改。 谨慎实施。当父表记录删除了,子表记录被自动删除。 放心实施。对于存在子表数据的主码不允许修改。 放心实施。对于存在子表数据的父表记录不允许删除。 绝对实施。当父表中不存在外码对应的记录,子表不允许插入数据。 说明 那么,用户定义的参照完整性如何实现?一般的DBMS都提供了相应的对策,如:Check约束、Null约束、索引约束、触发器、存储过程等。SQL Server 中还提到了域约束。在SQL Server 2000的联机丛书中都详细地阐述了上述所有的完整性约束,以及如何操作SQL Server2000去实现这些完整性约束。
表 3 SQL Server 2000 中用户定义约束的实施
约束方法 Check约束 使用“企业管理器”构建。 使用“Create/Alter Table „ Check”的SQL构建。 Null约束 使用“企业管理器”构建。 使用“Create/Alter Table „ Null/Not Null”的SQL构建。 索引约束 使用“企业管理器”构建。 使用“Create Index”的SQL构建。 触发器约束 使用“企业管理器”构建。 使用“Create/Alter Trigger”的SQL构建。 存储过程 使用“企业管理器”构建。 使用“Create/Alter Procedure”的SQL构建。 说明
1.2 实验目标
能使用SQL Server 2000创建完整性约束。
1.3 实验任务
序号 1 2 3 4 5 任务 本次实验需要用到SQL Server 2000。 创建实验7的数据库,取名为“SalesDB”。 为每个表创建主码。 为所有存在关系的表构建参照完整性约束。 列出不能为Null的非主码字段,并加入Not Null约束。 经济管理学院,2004
Page 2 of 6
数据库系统原理,《实验指导书》 6 使用Check约束,确保: (1) 订货数量、未发货量不能为小于0的数。 (2) 折扣金额不能大于订货金额。 7 使用触发器约束,确保: (1) 未发货数量随着每笔订单的发货,而自动减少。
经济管理学院,2004
Page 3 of 6
数据库系统原理,《实验指导书》
2 实验报告
2.1 实验人信息
姓名:____XXX___________学号:_____
实验时间:____________________________
2.2 实验结果
1. 写出每张表及其主码:
答:①、表 Customer :其主码为: CustomerID
②、表 Order : 其主码为: OrderID
③、表 Products : 其主码为:ProductID
④、表 Suplies :其主码为: ManufacterID 和 ProductID
经济管理学院,2004
Page 4 of 6
数据库系统原理,《实验指导书》
⑤、表 OrderDetails :其主码为:OrderID 和 ProductID
⑥、表 Manufactures : 其主码:ManufactureID
2. 写出父表和子表的关系以及它们的参照完整性强度:
答:①、顾客(父表)—订单(子表):使用了级联更新参照完整性约束和插入参照完
整性约束。
②、订单(父表)—订单细则(子表):使用了级联更新参照完整性约束和删除参
照完整性约束及插入参照完整性约束。
③、货物(父表)—订单细则(子表):使用了插入参照完整性约束、删除参照完
整性约束和更新参照完整性约束。
④、供应商(父表)—订单细则(子表):使用了插入参照完整性约束、更新参照
完整性约束和插入参照完整性约束。
⑤、制造厂商(父表)—货物(子表):使用了删除参照完整性约束、插入参照完
整性约束和更新参照完整性约束。
3. 写出所有不能为Null的非主码字段及其所在的表,并写出其中一个Not Null约束的
创建SQL:
答:①、顾客号(顾客),收货地址(顾客),赊购限额(顾客),余额(顾客),折扣
(顾客)。
②、货物名(货物),单价(货物),制造厂商号(货物),最低存货量(货物)
制造厂商名(制造厂商),实际存货量(制造厂商),地址(制造厂商)。 ③、订货数量(订单细则)。
④、顾客号(订单),收货地址(订单),订货日期(订单)。 Not Null约束的创建SQL:
customerName nvarchar(10) not null, balance float not null, discount float not null, credit float not null, address xml not null,
Page 5 of 6
经济管理学院,2004
数据库系统原理,《实验指导书》
4. 写出任务6中的创建Check约束的SQL: 答 :Check约束的SQL:
constraint CK_orderDetails_quantity check
(quantity>0 and actualShipment>=0 and actualShipment<=quantity),
constraint CK_customers_discount check (discount>0 and discount<=1),
5、写出任务7中的创建触发器约束的SQL:
答:使用触发器约束。未发货数量随着每笔订单的发货,而自动减少,其触发器约束
的SQL为:
CREATE TRIGGER unshipperquantity ON orderdetails
FOR UPDATE,INSERT AS
BEGIN
declare @unshipperquantity int declare @orderID int declare @ProductID int declare @OrderePrice int
declare myCursor cursor for
select unshipperquantity, orderID, ProductID from inserted
open myCursor
fetch myCursor r into
@unshipperquantity, @orderID, @ProductID, @OrderePrice while(@@FETCH_STATUS = 0) begin
set @unshipperquantity = @quantity - @actualShipment update orderdetails set @unshipperquantity = @unshipperquantity where orderID = @orderID and cargoID = @cargoID fetch myCursor into
@quantity,@actualShipment,@orderID,@cargoID end
close myCursor
deallocate myCursor; END
经济管理学院,2004
Page 6 of 6