分类
技术文章 数据库

关系数据库系列文章之到底什么是关系(一)

在语言X中如何实现Y,像这种具体的只是(know-how)可快速提高你的工作效率。但是一旦语言发生变化,这种知识就无法再使用。世界瞬息万变,这意味着限定了应用范围的具体知识将慢慢失去其价值。因此,我们不仅要学习具体的知识,更要有意识的去学习那些应用范围广泛的抽象的概念。—-摘自《代码之髓》 【日】西尾泰和

作为程序员,在日常的开发中,我们避免不了的就要接触数据库这个概念,而关系数据库以及其对应的SQL也是我们经常接触的概念。但我们也许都不曾认真的去探索它们名称背后的意义所在,而数据库相关的计算机知识发展迅速,所以掌握基本的理论基础,便可以使得我们可以在瞬息万变的技术更迭中触类旁通。为了达到上述的目的,我创作了关于关系数据库的系列文章,这是该系列文章的第一篇,探讨关系数据库中的所谓的“关系”。

我们学习数据库,首先要知道数据库是什么,根据相关的资料显示,数据库的定义如下:  数据库是长期存储在计算机内有组织、大量、共享的数据集合。它可以供各种用户共享,具有较小的冗余度和较高的数据独立性。概括的讲,数据库具有永久存储,有组织和可共享三个基本特点。

更加通俗的说,数据库就是一个使用特定数据结构(如:B+ 树)长期存储在计算机上的一个数据的集合。

概念如此,浅显易懂。但是我们平时跟数据库分类,所谓的关系数据库,非关系数据库等,这些依据又是从何而来的呢?首先,我们要知道数据库的发展是沿着数据模型的主线进行推进的。

什么是数据模型,我们要着重介绍一下。

模型,对我们来说并不陌生, 一张地图,一架航模飞机都是具体的模型,一眼看去就是使人们联想到真实生活中的事物。所以,模型就是对现实世界中某个对象特征的模拟和抽象。而数据模型也是一种模型 ,它是对现实世界数据特征的抽象。也就是说,数据模型是用来描述数据、组织数据和对数据进行操作的。生活中处处都是数据,比如说,学校中的每个教室和学生每个人就是一个独立的数据,这个数据包含各种属性,如:姓名,身高,年级等等,而某个老师教哪些学生,哪些班级,哪些学生与哪些学生又是同学等等,这些庞大的数据以及数据关系充斥在我们的现实生活中,我们习以为常并不觉得难懂,但如果将这些数据存入计算机中,该如何存入呢,当然会有很多方式,但是我们首先要做的就是将这些数据转化成计算机能处理的数据,这一步叫做数字化,然后将现实生活中的概念用数据模型进行抽象、表示、处理,通俗的讲,数据模型就是现实世界的模拟。可以这样理解,我们存入计算机的数据就是单纯的数据,如:(张三、170、2)就是一条数据,而我们要对这些数据进行表示操作的时候,就要通过数据模型还原成现实世界进行操作,如:姓名:张三,身高:170cm, 二年级,当我们修改年级为0的时候就是违法操作,因为现实中没有0年级。(这里只是举个例子)

现有的所有数据库都是基于某种数据模型的。数据模型是数据库系统的核心和基础。

人们把数据模型分为两类:第一类是概念模型,第二类是逻辑模型和物理模型。概念模型主要是按照用户的观点对数据和信息建模主要用于数据库设计。第二类中逻辑模型主要包括,层次模型、网状模型、关系模型、面向对象数据模型等,主要用于数据库管理系统的实现。而第二类中的物理模型是对数据最底层的抽象,描述数据在系统内部的表示方式和存取方法,或在磁盘上的存储方式和存取方法,是面向计算机系统的。

注:数据库管理系统和操作系统一样是计算机的基础软件,也是一个大型复杂的软件系统。下文统称为DBMS

到这里,我们可以总结一下了:数据库就是一个数据集合,它存储在硬盘上(也可能是内存中),具体怎么存,怎么读取使用物理模型进行抽象,它面向的是计算机系统。这些最底层的数据最终是要被数据库管理系统操作的,而数据库管理系统中存在某种数据模型对所有底层的数据进行建模,如果使用关系模型,该数据库即是关系型数据库。

这里跳过层次模型和网状模型的介绍,因为这两种模型已经逐渐被市场淘汰(个人了解),简单说下其优缺点吧,层次数据库就像是一个二叉树,所以每个数据都有从根节点出发而来的路径信息,所以检索性能高,但是由于是一对多的关系并不能满足现实世界中多对多的情况,且插入和删除操作的限制比较多,查询必须通过双亲节点,程序的编写也比较复杂。而网状数据库虽然可以直接描述现实世界,但是结构比较复杂,应用程序编写麻烦。

进入现在应用广泛的关系数据库,那我们就要先了解关系模型,因为采用关系模型作为数据结构的数据库被称为关系数据库。  

什么是关系模型?这里简单勾画一下关系模型,从用户的观点看,关系模型是由一组关系组成的。而每个关系的数据结构是一张规范化的二维表。如下,以一个表为例介绍几个概念:

学生登记表:

关系:一个关系对应通常说的一张表,如上图这张表。元组:表中的一行即为一个元组。属性:表中的一列即为一个属性,给每一个属性起一个名称即属性名,如上图对应着四个属性(学号,姓名,年龄,性别)码:也称为码键。表中的某个属性组,它可以唯一确定一个元组,如上图中的属性学号可以 唯一确定一个学生,也就成为了本关系的码。关系模式:对应关系的描述,一般表示为 关系名(属性1、属性2),如上的关系可以描述为:学生(学号、姓名、年龄、性别)

 这是关系模型中一些基本的概念, 除此之外,关系模型要求关系必须是规范化的,即要求关系必须满足一定的规范条件,这些条件中最基本的一条就是,关系元组中的每一个属性值必须是一个不可分的数据项,也就是说,不允许表中还有表。例如,上图表中,新增一列“成绩”,在成绩中又划分,数学、C语言等,这种情况就不满足规范化。

到此,你可能会豁然开朗,原来一个现实生活中的二维表,就是一个关系。

这只是我们从定义的概念中“推测”而来的“大致”的一个总结,还不能到达到知其所以然的目的。那么我们就要重新回到数据模型的角度来看待问题,首先要知道的是,数据模型有三大要素组成:数据结构、数据操作、数据的完整性约束条件三部分组成。所以我们要去了解一个数据模型,就要从这三方面着手,而了解一个数据库同样如此。所以我们有必要知道,关系模型对应的上述三要素,下面进行详细的阐述:

数据结构:

从上面勾画的概念中我们大致知道,关系模型的数据结构就是—-关系,这种关系在用户看来就是一张扁平的二维表。且这种结构是严格建立在数学概念基础上的,要想具体了解,我们首先要知道如下几个小概念:

1、域:域是一组具有相同数据类型值的集合。例如:整数、自然数、长度小于25字节的字符串集合、{0,1}、{男、女},这些都可以是域。2、笛卡尔积:笛卡尔积是域上的一种集合运算,给定一组域,D1、D2…Dn,允许其中某些域是相同的,则D1、D2…Dn的笛卡尔积:D1×D2×…×Dn={(d1,d2,…,dn) | di∈Di,i=1,2,…,n},这是一个简单的集合表达式,即有多少个域进行运算,其结果集合中的每个元组就有多少个列,而第i列的取值范围属于域Di,举个例子:现在有域 A{1,2,3},B{7,8},这两个域的笛卡尔积可以表示为一个大集合:{(1,7),(1,8),(2,7),(2,8),(3,7),(3,8)},结果集合中共有6个元素(也可以称为元组),而元素的个数可以通过域元素数量相乘得到,即:3*2=6。现在,我们可以这样总结笛卡尔积:笛卡尔积描述的是两个或多个集合相互“关联”成一个最终的集合,而这个最终的集合将包含“关联”之后所有的“可能性”。

我们现在将上述笛卡尔积概念中描述的“关联”运用到现实世界中,还是举学校的例子,将所有的学生姓名当成一个域,所有的年龄也列出来一个域,年级同样如此。现在就有三个域分别表示学生姓名,年龄,年级,即A{小明,毛羽,小芳},B{8,9},C{一年级,二年级},这三个域本来独立存在且不相干的三个域,但是由于它们在某种意义上都对“学生”这个实体进行了描述,所以我们把这三个域进行笛卡尔积处理,也就是说把这三个域“关联”起来形成一种“关系”,这种关系是我们根据数学概念计算出来的。

计算结果为:{(小明,8,一年级),(小明,9,一年级),(小明,8,二年级),(小明,9,二年级),(毛羽,8,一年级),(毛羽,9,一年级),(毛羽,8,二年级),(毛羽,9,二年级),(小芳,8,一年级),(小芳,8,二年级),(小芳,9,一年级),(小芳,9,二年级)}

将上述结果集合加上每个列的属性名称形成一张二维表:

可以说,这张表就是我们根据三个自定义属性关联而成的一张“关系”表。但是这个关系结果是包含了所有的可能性的关系(所有可能往往是没有意义的,如上述例子中小芳只可能在一个年级中。所以笛卡尔积的真子集才有实际含义),而关系数据库中的结果正是这种所有可能性结果的子集。现在我们可以对关系模型中的“关系”进行定义:

D1×D2×…×Dn的子集叫做在域D1,D2…Dn上的关系,表示为R(D1,D2,…,Dn)这里的R表示关系的名字。关系是笛卡尔积的有限子集,所以关系也是一张二维表,表的每行对应一个元组,表的每列对应一个域。由于域可以相同,为了加以区分,必须对每列起一个名字,称为属性。

由于组成笛卡尔积的域不满足交换律,所以按照数学定义,(d1,d2,…,dn)≠(d2,d1,…,dn)。当关系作为关系数据模型的数据结构时,需要加上如下的限定和扩充:

1、无限关系在数据库系统中是无意义的,所以,限定关系数据模型中的关系必须是有限集合。2、通过为关系的每个列附加一个属性名的方法取消关系属性的有序性,即(d1,d2,…,dn)=(d2,d1,…,dn)

注:关系有三种类型:基本关系(通常又称为基本表或基表)、查询表和视图表。其他的内容我们会在之后的文章进行详细的介绍。

1、列是同质的,即每一列中的分量是同一类型的数据,来自同一个域。联想:我们在建立数据库字段时要指定其字段类型,如int,varchar等。2、不同的列可出自同一个域,称其中的每一列为一个属性,不同的属性要给予不同的属性名,如上面的例子中我们可以给出属性名:姓名={小明,毛羽,小芳}。年龄={8,9}。3、列的顺序无所谓,即列的次序可以任意交换。由于列顺序是无关紧要的,因此在许多实际关系数据库产品中增加新属性时,永远是插在最后一列。4、行的顺序无所谓,即行的次序可以任意交换。5、任意两个元组的候选码不能取相同的值。

注:若关系中的某一属性组的值能唯一的标识一个元组,而其子集不能,则称为该属性组为候选码。

6、分量必须取原子值,即每一个分量必须都必须是不可分的数据项。

注:分量,元素中的每一个值叫做一个分量,如上例中,小芳就是一个分量。

另,我们在上文中提到过:关系模型要求关系必须是规范化的,即要求关系必须满足一定的规范条件,这些条件中最基本的一条就是,关系元组中的每一个属性值必须是一个不可分的数据项。而规范化的关系成为范式(Normal Form NF),关于范式的概念将在后续的文章中详细介绍。

至此,关系数据模型中的数据结构介绍完毕。

但是就像上文所说,了解关系数据库要从其三要素(数据结构、数据操作、数据的完整性约束)着手,我们在了解了关系数据库的数据结构之后,对其概念有了深刻的认知,接下来的文章将结合SQL介绍关系数据库中的数据操作,以及数据的完整性约束,最终在充足的理论基础上再去了解具体的关系数据库(如:MySQL、Oracle、db2等)将更加简单与深刻。

本文部分内容参考《数据库系统概论》,且由于博主水平有限,文章中出现的错误或对关系数据库理解不当之处还望不吝赐教。还有,转载要注明出处哦。