第五章-数据库完整性
本章重点
- 实体完整性
- 参照完整性
- 用户定义的完整性
概述
数据库的完整性是指数据的正确、有效、相容。
为维护数据库的完整性,数据库管理系统必须能够实现如下功能:(要背过)
- 提供定义完整性约束条件的机制
- 提供完整性检查的方法
- 进行违约处理
实体完整性
实体完整性检查:
- 检查主码值是否唯一,如果不唯一则拒绝插入或修改。
- 检查主码的各个属性(主码可能有多个属性)是否为空,只要有一个为空就拒绝插入或修改。
检查主码是否唯一可以使用全表扫描的方法,但由于效率低下,可以通过建立索引的方式提高效率(如B+树)。
参照完整性
定义参照完整性
通过定义外码来实现。
外码:不是本关系的主码,但是是另外一个关系中的主码。
参照完整性检查和违约处理
e.g. 显式说明参照完整性的违约处理示例。
CREATE TABLE SC
( Sno CHAR(9),
Cno CHAR(4),
Grade SMALLINT,
PRIMARY KEY (Sno, Cno),
FOREIGN KEY (Sno) REFERENCES Student(Sno)
ON DELETE CASCADE;
ON UPDATE CASCADE;
FOREIGN KEY (Cno) REFERENCES Course(Cno)
ON DELETE CASCADE;
ON UPDATE CASCADE;
);
这里的ON DELETE CASCADE和ON UPDATE CASCADE分别代表在删除环节和更新环节级联操作,能够保证参照完整性。
用户定义的完整性
属性上的约束条件
- 列值非空(NOT NULL)。 e.g. Student表姓名非空
- 列值唯一(UNIQUE)。 e.g. 手机号不能重复
- 检查列值是否满足一个条件表达式(CHECK短语)。
e.g. (用CHECK短语指定列值应该满足的条件)Student表的Ssex只允许取“男”或“女”。
CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY,
Sname CHAR(8) NOT NULL,
Ssex CHAR(2) CHECK (Ssex IN ('男','女')), /* Ssex只允许取“男”或“女” */
Sage SMALLINT,
Sdept CHAR(20)
);
元组上的约束条件
在CREATE TABLE语句中可以用CHECK短语定义元组上的约束条件,即元组级的限制。同属性值限制相比,元组级的限制可以设置不同属性之间的取值的相互约束条件。
e.g. 当学生的性别是男时,其名字不能以Ms.开头。
CREATE TABLE Student
(Sno CHAR(9) PRIMARY KEY,
Sname CHAR(8) NOT NULL,
Ssex CHAR(2),
Sage SMALLINT,
Sdept CHAR(20),
CHECK (Sname NOT LIKE 'Ms.%' OR Ssex='女') /* 定义了元组中Sname和Ssex两个属性值之间的约束条件 */
);
完整性约束命名子句
CONSTRAINT <完整性约束条件名><完整性约束条件>
理解:相当于给约束条件起个名字,方便后续对这些约束条件进行调整。
e.g. 建立学生登记表Student,要求学号在90000到99999之间,姓名不能取空值,年龄小于30岁,性别只能是“男”或“女”。
CREATE TABLE Student
(Sno NUMERIC(6)
CONSTRAINT C1 CHECK(Sno BETWEEN 90000 AND 99999),
Sname CHAR(20)
CONSTRAINT C2 NOT NULL,
Sage NUMERIC(3)
CONSTRAINT C3 CHECK(Sage<30),
Ssex CHAR(2)
CONSTRAINT C4 CHECK(Ssex IN ('男','女')),
CONSTRAINT StudentKey PRIMARY KEY(Sno)
);
域中的完整性限制
域是一组具有相同数据类型的值的集合。
e.g. 建立一个性别域,并声明性别域的取值范围。
CREATE DOMAIN GenderDomain CHAR(2)
CHECK (VALUE IN ('男','女'));
断言
CREATE ASSERTION
可以定义涉及多个表或聚集操作的比较复杂的完整性约束。断言创建以后,任何对断言中所涉及关系的操作都会触发关系数据库管理系统对断言的检查,任何使断言不为真值的操作都会被拒绝执行。
CREATE ASSERTION <断言名><CHECK子句>
e.g. 限制数据库课程最多60名学生选修。
CREATE ASSERTION ASSE_SC_DB_NUM
CHECK (60 >= (SELECT count(*)
FROM Course, SC
WHERE SC.Cno=Course.Cno AND Course.Cname='数据库')
);
删除断言:
DELETE ASSERTION <断言名>;
触发器(了解)
TRIGGER