写程序时,如果有存储的需求,那往往会用到数据库。
如果你是初次使用,或者是半路出家,那在数据库选型时可能就会纠结,这么多数据库,到底该选哪种呢?
一般来讲,都是会选比较主流的,如MySQL、SQL Server、Oracle、SQLite等(当然具体还是得根据你的需求来),其实不管是这里的哪种,你在查询相关资料时,总能发现它的介绍是一种关于xxx的关系数据库。
如果把关系两字去掉,变成它是一种xx的数据库,那我就不会有什么疑问了。
数据库嘛,不就是存储数据的,很好理解啊。
那关系两字的意义何在?为什么好多主流数据库都是关系数据库?
显然这个问题不是一两句话能讲清的。
先从一个例子说起,
假如让你在不用数据库的情况下,实现一个图书管理系统(或者其它的管理系统也好,就是类似于大学课程设计的那种),那信息的存储部分你会怎么写。
简单说说我当时是怎么写的,实现上是用文件的方式来实现的。我当时是用C语言+控制台做的这么一个系统。像数据模型,就用结构体来实现:
struct Book
{
char BookName[NAMELEN];
char Publisher[NAMELEN];
...
}
数据存储,就用读写文件来做,
在读写上,就要注意格式,读到的第一串字符是书名,空格之后是出版社,然后两条记录之间用换行隔开。这些文件的格式要与你代码中的读写方式一一对应。
现在看这些实现可能会觉得很幼稚,漏洞百出,鲁棒性很差。但实际上在刚刚接触编程时,能用链表、文件IO来实现这么一个系统是一件挺有成就感的事情。
在我看来,它就是数据库的前身。
那什么是数据库呢?
借用wiki百科的一句话。
数据库是指长期存储在计算机内有组织的、可共享的数据集合。
单从这几点来看,我觉得之前用文件实现的存储功能也可以被称为数据库:
不过这是我站在现在的角度来看当时做出来的这一坨系统,事后分析它,发现它居然符合数据库的所有特点。
显然这是一个比较广义的角度来看的。实际上,就算我自己,现在也不会称这种文件存储为数据库存。
那我们平时说的数据库,MySQL、SQL Server、Oracle、SQLite等到底是指什么呢?
我打开了百度,输入了这些关键字,得到了如下信息:
原来平时说的数据库都是指数据库管理系统(DataBase Management System,简称DBMS)。
多了管理系统四个字,就与广义的数据库区分开来了,这四个字意义何在?
我们先来看系统两字,
系统一词来源于英文system,即若干部分相互联系、相互作用,形成的具有某些功能的整体。
没错,它是一个具有多功能的整体。
你打开任意一个主流的“狭义”数据库,都可以发现,它绝不只是一个具有存储功能的程序,它的配套软件、配套文档绝对对得起系统两字(数据库核心本身、图形化管理工具、开发接口、驱动、连接器、配置工具等等)。
这一节是后来补充进来的,所以看着有些突兀。
但是要说关系数据库,它也不是一开始就有的。而是发展到了一定阶段才出现的。
数据库是拿来存储数据的,是因为人们有长期存储数据的需求而诞生的。
存储必然会涉及到数据的分类、存储结构、存取方式等一系列问题。
像我这种小白第一次接触数据存储,都知道应该将数据进行一定组织按照一定格式来存取,这么多的计算机科学家、工程师会不知道这一点?
他们当然知道,他们不仅知道,他们还想着创造出一套通用的存储方式,他们还想着设计出现实世界的抽象模型(计算机毕竟是虚拟世界,许多事物得借鉴现实世界,所以在设计上往往会从现实世界中抽象),来彻底地解决这一问题。
于是凭借着对世界的认知,他们前后设计出了,层次模型(树状模型)、网状模型(图状模型)。
中学时期教过生物的分类,界门纲目科属种。
只要你是生物,那就可以按这个分类,一层层往下找,最后就能找到你所属的类别。
层次模型就是这样的,模拟了现实世界对各种事物的分层(每层都记录自己的一些特性),
很明显,层次结构相比于我的C语言文件存储功能,它能体现出不同事物之间的联系了,尤其是层次关系。
但现实世界可没有那么简单,并不是所有关系都是层次的。鲨鱼能吃人,那人反过来还能吃鲨鱼呢。
网状模型很好的解决了这一问题,
网状模型和图这种数据结构类似,只要你想,那就能在不同事物间添加路径(即联系)。甚至某种程度上来说,网状模型才是最符合现实世界的。哲学上说万物皆有联系嘛。但是在计算机世界中,完美的模型可不见得是最好的。网状模型结构复杂,数据操作复杂,用户不容易使用。数据独立性差,各种数据间都有联系。而且应用环境越大,数据结构就指数倍的复杂。你啥联系都有,那我还写不写程序了嘛。(或许在未来算力、空间都高度发达的情况下,这种模型会再次崛起。像现在的元宇宙概念,我觉得这个模型就挺符合的)
于是基于关系模型的数据库就出现了。
1970年,IBM实验室的研究员考得发表了一篇论文,提出了基于集合论和谓词逻辑的关系模型,为关系型数据库技术奠定了理论基础。随后,他又陆续发表了多篇文章,论述了范式理论,用数学理论奠定了关系数据库的基础,为关系数据库建立了一个数据模型———关系数据模型。
与前两个模型不同的是,关系模型是有严格的数学基础在背后做支撑。
以往模型中使用者在查找一个数据时,往往需要在脑海中构建出当前的层次结构或网络结构,
接着才能按照关系编码再查找,若一个系统实体数量庞大,这就让人力难以企及了。
而对关系数据库的操作是高度非过程化的,用户不需要指出特殊的存取路径,路径的选择由DBMS的优化机制来完成。
关系数据模型的概念简单,结构灵活,能满足所有布尔逻辑运算和集合运算规则形成的查询要求; 可以搜索、比较和组合不同类型的数据; 使用关系数据模型进行数据增加和删除操作非常方便,关系数据模型具有较高的数据独立性和更好的安全保密性。
关系模型最大的创新点是拆掉了表与表之间的联系,将这种关系只存储在表中的一个字段中,从而实现了表与表之间的独立。
那说了这么多,到底什么是关系数据模型?
这边还是引用度娘上的话,
关系数据模型是在关系结构的数据库中用二维表格的形式表示实体以及实体之间的联系的模型。
其实不光是度娘,几乎所有的blog上的说法都是这句话。
至于为什么它是一张二维表。我想和关系数据模型背后的数学概念有关。
关系模型是源于集合论的,
我不是数学系的,不会说太多数学的东西(免得露馅了),
不过集合这个概念,高中就有教过,还记得其操作有并∪、交∩。
举个例子,
A补习班有四个同学(A、B、C、D)报名,B补习班有四个同学(B、C、D、E)报名,求同时报名A、B补习班的有哪几个同学。
很简单,B、C、D嘛。
用集合运算表示, 集合A∩集合B = (B、C、D)。
谈到程序设计,很容易想到将现实事物抽象成模型,那么用面向对象的思想该怎么抽象呢?
// 用面向对象的方式把一个现实事物(比如说人)给抽象,提取其特征Name、Age、Height、Weight
class Person
{
Name;
Age;
Height;
Weight;
}
// 再将A实例化几个对象
Person p1 = new Person(){ Name = "Lily", Age = 21, Height = 161, Weight = 55 };
Person p2 = new Person(){ Name = "Sara", Age = 22, Height = 162, Weight = 56 };
Person p3 = new Person(){ Name = "Colman", Age = 23, Height = 163, Weight = 65 };
将类型Person与实例平铺,很容易得到下面的表,
Name | Age | Height | Weight |
---|---|---|---|
Lily | 21 | 161 | 55 |
Sara | 22 | 162 | 56 |
Colman | 23 | 163 | 65 |
我想,你可以认为二维表是这么来的。这样的二维表不管是纵向还是横向也都很容易看成集合做集合运算。
事实上,在关系数据库中,确实有概念与这些面向对象的思想的抽象模型对应,正好借此机会,将几个基本概念理解一下:
字段这个东西,我更喜欢叫它属性,因为属性跟面向对象就挂钩了,更易于理解。每个属性的值,对事物都是具有描述意义的。这个人身高1米8,那1米8就很好地描述了一个人的身高特征。
有一说一,在初学时看到元组这个词,而且毫无解释说明,会感觉挺抵触的。
就好像有人跟你讲一个生活中常见的东西,在某个领域里的名称是一串很奇怪的数字,你根本无法理解,为什么要取这种奇怪的名字。
不过在这里的元组,或许可以强行理解一下。
元这个字,在计算机中有特别的含义:
元数据,指描述数据的数据。
元类,指代表类的类。
所以 元组呢?
描述组的组。从它的构成来看,是由一行属性值构成,每个属性值都可以一定程度上描述一个对象。所以这一组的属性值也可以很好地描述一个对象。那按照元组在计算机领域的字面意思来就说得通了。
还是吐槽一下命名,主键,甚至主码,一般都是叫这两个吧。其实很明显,主键就是英文major key翻译而来的,但是对于初学者来讲,主关键字这种叫法不是更浅显易懂吗。
英文是domain,这个怎么说呢,域也确实不难理解,因为domain这个词一般都这么翻译。但还是觉得范围或者取值范围更好。
其实这里的部分概念用关系数据库背后的数学来描述会更严谨一些,如关系就是笛卡尔积的子集,关系模式可以描述为R(U,D,DOM,F)等。不过本文不打算做细致讲解,只想对关系数据库做概述。
接下来了解一下关系模型中的约束。
约束,字面意思也清晰,就是限制,那限制啥呢?
关系数据模型的操作主要包括查询、插入、删除和修改数据(常说的增删改查,CRUD)。约束就是来约束这些操作的,从而最终约束数据,约束整个关系(整张表)。也就是说,这些操作都要满足约束条件。
约束的条件被称为关系的完整性约束,很明显,关系不是你想定义就定义的,它需要参照三种完整性的原则:
学号 | 姓名 | 专业 |
---|---|---|
1 | Lily | 计算机 |
2 | Lyles | 扫地 |
专业号 | 专业名 |
---|---|
计算机 | 1001 |
软件工程 | 1002 |
显然扫地这个专业并不存在,就违反了参考完整性。
学号 | 姓名 | 年龄 |
---|---|---|
1001 | Lily | -1 |
年龄这个字段应该是不能为负数的,这边显然不符合语义。
本文将关系数据库的由来,基本概念简单介绍了下。
现在总结一下几个要点: