关系数据库系列文章之数据库的完整性(三)

本文为作者原创内容,未经许可,禁止转载。如您发现侵权行为,请联系我们

在前面的文章中我们已经提到过了,想要系统的学习了解数据库要从三个方面入手:数据结构、数据操作、以及数据的完整性。

什么是数据的完整性,数据的完整性主要有三个方面:实体、参照、用户自定义。所以数据库完整性也是由这三个部分组成。这些完整性的就是指的是数据的正确性、相容性。正确性主要是指数据满足数据库管理系统的定义,而相容性指的是关系与关系之间数据的一致。

感觉有点抽象不好理解,那我们下面就分别对三个完整性具体的讲讲。

一、实体完整性:


首先要讲的是,什么是实体完整性。我们前面有提到过,实体描述的就是一个关系的抽象概念,比如,一个关系(即一个表)中主要存的就是学生的信息(姓名、年龄等信息),那么这个表可以叫做
学生表,而对应的实体可以看做是学生,那么实体完整性指的就是,一个表中主键(主码)的约束,也就是说对关系中每一行都进行唯一性约束,即实体的完整性约束。

当我们使用,PRIMARY KEY短语定义了关系的主码后,每当我们对表插入一条数据或更新时,关系数据库管理系统都会对关系的实体完整性规则进行自动检查:

1、检查主码的值是否唯一,如果不唯一则拒绝插入或修改。
2、检查主码的各个属性是否为空(主码可以由多个属性进行组成),只要有一个为空就拒绝插入或修改,从而保证了实体完整性。

补:值得注意的是,检查记录中的主码值的唯一方法就是进行全表扫描,而我们每一次对表的操作都会伴随着全表扫描,这将是一个非常耗时的操作。为了避免对基本表进行全表扫描,关系数据库管理系统一般都在主码上自动建立一个索引,通过索引查找基本表是否已经存在新的主码将大大提高效率。(关于索引的原理以及背后的算法,我们将在后续的文章中进行讨论)


二、参照完整性:

可以这样理解,参照完整性指的是,关系与关系之间的约束,即表与表之间的约束。举个简单的例子,有学生实体如:学生(学号、年龄、...) 课程实体:课程(课程编号、名称、代课老师...),上面两个表中的主键分别对应的是:学号,课程编号。现在我们要新建一个表,学生的成绩表,如:成绩(学号、课程编号、成绩...),成绩表中的主键就是学号和课程编号,因为其中的任意一个属性都不能唯一确定一个元组,而这两个属性的值分别来自学生表和课程表中的主键,也称这两个属性参照引用了另外两个表的主键,这两个属性也叫做外键,那么对其中一个表中的元组进行操作时,必须保证其涉及的另外的表的数据的完整,这成为参照完整性。

参照完整性在CREATE TABLE中用FOREIGN KEY短语定义哪些列为外键。

那进行什么操作,参照完整性会进行约束呢?

就上面的例子来说,有两种情况:
1、当我们在成绩表中增加修改外键时,导致在学生表或课程表中找不到与之对应的数据。
2、反过来,新增或者修改学生或课程表时,导致成绩表中的某些元组在另外两张表中找不到对应的元组。

如果我们定义了参照完整性约束,系统检测到违规操作,会如如何执行呢?
默认的执行是:拒绝,拒绝违反参照完整性的的新增以及更新操作。
我们也可以自定义其他的操作:级联操作(级联修改,级联删除)、设置为空值 这两种操作。

示例如下:

create table SC(
sno char(9),//学号
cno char(4),//课程编号
grade smallint,//成绩
primary key(sno,cno),//定义了实体完整性,sno,cno不能为空
foreign key(sno) references student(sno),//定义了参照完整性

on delete cascade
on update cascade,//当删除更新学生表时,级联删除或更新SC中对应的元组

foreign key(cno) references course(cno),

on delete no action
on update cascade //当删除课程表中的数据时候,拒绝删除,更新时,对参照表级联更新

);

三、用户定义的完整性


用户定义的完整性就是针对某一具体应用的数据必须满足的语义要求。目前的关系数据库管理系统都提供了定义和检验这类完整性的机制,使用了和实体完整性、参照完整性相同的技术和方法来处理它们,而不必有应用程序承担这一功能。

约束大致分为两类:属性上的约束条件、元组上的约束条件

1、属性上的约束

(1)不允许空值(not null)。
如:create table sc(
sno char(9) not null;//属性不允许取空值
cno char(4) not null;
primary key (sno,cno)
...
);



(2)列值唯一(unique)。

create table test(
id int;
name char(9) unique not null,//要求name列值唯一,且不能取空值
primary key (id)
);



(3)使用check短语指定列值应该满足的条件

create table student(
sno char(9) primary key,//在列级别中定义主键,上面的例子都是在表级别中定义的主键
sex char(2) check(sex in ('男','女'))//性别属性只允许男或女
age smallint check(age>=0 and age<=100)//年龄的取值范围是0到100
);


如果违反用户自定义的完整性约束时,将拒绝操作。


2、元组上的约束条件

    元组上的约束条件语属性的约束条件类似,也是使用check短语进行操作,与之不同的是,元组级别的限制可以设置不同属性之间的取值的相互约束条件。


create table student(
sno char(9),
name char(8) not null,
sex char(2),
primary key (sno),
check (sex='女' or name not like 'MS.%')//定义了元组中name 与sex两列的约束条件
);//即要求如果性别是男的时候,其名字不能以MS.打头


这里补充一下其他的字句:
constraint bingo check(sno between 100 and 200)//使用constraint 字句对完整性约束条件进行命名为bingo
alter table student drop constraint bingo;删除完整性约束bingo
alter table student add constraint bingo check(sno between 100 and 200)//新增完整性约束

完整性约束部分的内容到此结束。至此,关系数据库中的基本概念性内容都已经系统的了解了,接下来就要涉及关系数据库的应用设计了内容了,如何设计一个可用合理的关系数据库将是我们关心的内容,接下来的文章我们主要要了解范式的概念,以及如何做到规范化。