• 关系数据库是个啥


    一、引言

    写程序时,如果有存储的需求,那往往会用到数据库。
    如果你是初次使用,或者是半路出家,那在数据库选型时可能就会纠结,这么多数据库,到底该选哪种呢?
    一般来讲,都是会选比较主流的,如MySQL、SQL Server、Oracle、SQLite等(当然具体还是得根据你的需求来),其实不管是这里的哪种,你在查询相关资料时,总能发现它的介绍是一种关于xxx的关系数据库

    如果把关系两字去掉,变成它是一种xx的数据库,那我就不会有什么疑问了。
    数据库嘛,不就是存储数据的,很好理解啊。

    那关系两字的意义何在?为什么好多主流数据库都是关系数据库?
    显然这个问题不是一两句话能讲清的。


    二、过程

    1. 文件存储

    先从一个例子说起,
    假如让你在不用数据库的情况下,实现一个图书管理系统(或者其它的管理系统也好,就是类似于大学课程设计的那种),那信息的存储部分你会怎么写。

    简单说说我当时是怎么写的,实现上是用文件的方式来实现的。我当时是用C语言+控制台做的这么一个系统。像数据模型,就用结构体来实现:

    struct Book
    {
    	char BookName[NAMELEN];
    	char Publisher[NAMELEN];
    	...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    数据存储,就用读写文件来做,
    在这里插入图片描述
    在读写上,就要注意格式,读到的第一串字符是书名,空格之后是出版社,然后两条记录之间用换行隔开。这些文件的格式要与你代码中的读写方式一一对应。

    现在看这些实现可能会觉得很幼稚,漏洞百出,鲁棒性很差。但实际上在刚刚接触编程时,能用链表、文件IO来实现这么一个系统是一件挺有成就感的事情。

    在我看来,它就是数据库的前身。

    2. 数据库是啥

    2.1. 广义上的数据库

    那什么是数据库呢?
    借用wiki百科的一句话。

    数据库是指长期存储在计算机内有组织的、可共享的数据集合。

    单从这几点来看,我觉得之前用文件实现的存储功能也可以被称为数据库:

    • 长期存储,实际上就认为是它不只是存储在内存中的临时数据,而且还应该是断电重启后还能读取出来的存在于磁盘上的数据。
    • 有组织的,它的存储不是杂乱无章的,而是按一定格式存储的
    • 可共享的,指数据能为不同的用户、使用不同的语言、为不同的目的而同时存取。这个特性,其实加一些技术手段也完全可以做到。多线程+远程。
    • 数据集合,DataSet,这个概念一般指的是一批数据(而非仅仅是单个数据),但是也有很多说法是,数据间是相互有关的。一定要强行关联的话,我认为设计的结构体内的变量间也是有关联的。

    不过这是我站在现在的角度来看当时做出来的这一坨系统,事后分析它,发现它居然符合数据库的所有特点。

    显然这是一个比较广义的角度来看的。实际上,就算我自己,现在也不会称这种文件存储为数据库存。

    2.2. 平时说的数据库

    那我们平时说的数据库,MySQL、SQL Server、Oracle、SQLite等到底是指什么呢?
    我打开了百度,输入了这些关键字,得到了如下信息:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    原来平时说的数据库都是指数据库管理系统(DataBase Management System,简称DBMS)。

    多了管理系统四个字,就与广义的数据库区分开来了,这四个字意义何在?
    我们先来看系统两字,

    系统一词来源于英文system,即若干部分相互联系、相互作用,形成的具有某些功能的整体。

    没错,它是一个具有多功能的整体。
    你打开任意一个主流的“狭义”数据库,都可以发现,它绝不只是一个具有存储功能的程序,它的配套软件、配套文档绝对对得起系统两字(数据库核心本身、图形化管理工具、开发接口、驱动、连接器、配置工具等等)。

    3. 数据库发展史

    这一节是后来补充进来的,所以看着有些突兀。
    但是要说关系数据库,它也不是一开始就有的。而是发展到了一定阶段才出现的。

    数据库是拿来存储数据的,是因为人们有长期存储数据的需求而诞生的。
    存储必然会涉及到数据的分类、存储结构、存取方式等一系列问题。
    像我这种小白第一次接触数据存储,都知道应该将数据进行一定组织按照一定格式来存取,这么多的计算机科学家、工程师会不知道这一点?
    他们当然知道,他们不仅知道,他们还想着创造出一套通用的存储方式,他们还想着设计出现实世界的抽象模型(计算机毕竟是虚拟世界,许多事物得借鉴现实世界,所以在设计上往往会从现实世界中抽象),来彻底地解决这一问题。

    于是凭借着对世界的认知,他们前后设计出了,层次模型(树状模型)、网状模型(图状模型)。
    中学时期教过生物的分类,界门纲目科属种。
    只要你是生物,那就可以按这个分类,一层层往下找,最后就能找到你所属的类别。
    层次模型就是这样的,模拟了现实世界对各种事物的分层(每层都记录自己的一些特性),
    在这里插入图片描述
    很明显,层次结构相比于我的C语言文件存储功能,它能体现出不同事物之间的联系了,尤其是层次关系。

    但现实世界可没有那么简单,并不是所有关系都是层次的。鲨鱼能吃人,那人反过来还能吃鲨鱼呢。
    网状模型很好的解决了这一问题,
    在这里插入图片描述
    网状模型和图这种数据结构类似,只要你想,那就能在不同事物间添加路径(即联系)。甚至某种程度上来说,网状模型才是最符合现实世界的。哲学上说万物皆有联系嘛。但是在计算机世界中,完美的模型可不见得是最好的。网状模型结构复杂,数据操作复杂,用户不容易使用。数据独立性差,各种数据间都有联系。而且应用环境越大,数据结构就指数倍的复杂。你啥联系都有,那我还写不写程序了嘛。(或许在未来算力、空间都高度发达的情况下,这种模型会再次崛起。像现在的元宇宙概念,我觉得这个模型就挺符合的)

    于是基于关系模型的数据库就出现了。

    4. 关系数据库

    1970年,IBM实验室的研究员考得发表了一篇论文,提出了基于集合论和谓词逻辑的关系模型,为关系型数据库技术奠定了理论基础。随后,他又陆续发表了多篇文章,论述了范式理论,用数学理论奠定了关系数据库的基础,为关系数据库建立了一个数据模型———关系数据模型。

    与前两个模型不同的是,关系模型是有严格的数学基础在背后做支撑。
    以往模型中使用者在查找一个数据时,往往需要在脑海中构建出当前的层次结构或网络结构,
    接着才能按照关系编码再查找,若一个系统实体数量庞大,这就让人力难以企及了。
    而对关系数据库的操作是高度非过程化的,用户不需要指出特殊的存取路径,路径的选择由DBMS的优化机制来完成。
    
    • 1
    • 2
    • 3
    • 4

    关系数据模型的概念简单,结构灵活,能满足所有布尔逻辑运算和集合运算规则形成的查询要求; 可以搜索、比较和组合不同类型的数据; 使用关系数据模型进行数据增加和删除操作非常方便,关系数据模型具有较高的数据独立性和更好的安全保密性。
    关系模型最大的创新点是拆掉了表与表之间的联系,将这种关系只存储在表中的一个字段中,从而实现了表与表之间的独立

    那说了这么多,到底什么是关系数据模型?
    这边还是引用度娘上的话,

    关系数据模型是在关系结构的数据库中用二维表格的形式表示实体以及实体之间的联系的模型。

    其实不光是度娘,几乎所有的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 };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    将类型Person与实例平铺,很容易得到下面的表,

    NameAgeHeightWeight
    Lily2116155
    Sara2216256
    Colman2316365

    我想,你可以认为二维表是这么来的。这样的二维表不管是纵向还是横向也都很容易看成集合做集合运算。
    事实上,在关系数据库中,确实有概念与这些面向对象的思想的抽象模型对应,正好借此机会,将几个基本概念理解一下:

    • 关系:关系数据库中的表采用二维表格来存储数据,一个数据库可以包含任意多个数据表。这个二维表就叫关系,通俗地说,一个关系对应一张表
    • 字段(也称属性):数据表中的每一列称为一个字段。表是由其包含的各种字段定义的,每个字段描述了它所含有的数据的意义,数据表的设计实际上就是对字段的设计。
    • 属性值:行列交叉位置的值就是属性值。

    字段这个东西,我更喜欢叫它属性,因为属性跟面向对象就挂钩了,更易于理解。每个属性的值,对事物都是具有描述意义的。这个人身高1米8,那1米8就很好地描述了一个人的身高特征。

    • 元组(也称记录):代表数据表中的一行。元组的英文是tuple。

    有一说一,在初学时看到元组这个词,而且毫无解释说明,会感觉挺抵触的。
    就好像有人跟你讲一个生活中常见的东西,在某个领域里的名称是一串很奇怪的数字,你根本无法理解,为什么要取这种奇怪的名字。
    不过在这里的元组,或许可以强行理解一下。
    元这个字,在计算机中有特别的含义:
    元数据,指描述数据的数据。
    元类,指代表类的类。
    所以 元组呢?
    描述组的组。从它的构成来看,是由一行属性值构成,每个属性值都可以一定程度上描述一个对象。所以这一组的属性值也可以很好地描述一个对象。那按照元组在计算机领域的字面意思来就说得通了。

    • 主键(主码、主关键字):它是表中用于唯一确定一个元组的数据。关键字用来确保表中记录的唯一性,可以是一个字段或多个字段,常用作一个表的索引字段。每条记录的关键字都是不同的,因而可以唯一地标识一个记录,关键字也称为主关键字,或简称主键。

    还是吐槽一下命名,主键,甚至主码,一般都是叫这两个吧。其实很明显,主键就是英文major key翻译而来的,但是对于初学者来讲,主关键字这种叫法不是更浅显易懂吗。

    • 域:属性的取值范围。

    英文是domain,这个怎么说呢,域也确实不难理解,因为domain这个词一般都这么翻译。但还是觉得范围或者取值范围更好。

    • 关系模式:关系模式是对关系的描述。前面已经说过关系是一张二维表,那怎么描述一张表呢?从设计表的角度来看,主要是通过属性,我们设计一张表,往往是设计它有哪些属性,以及各个属性之间的依赖关系如何。所以一张表被设计出来后,它的模式总是固定的,而表本身是经常在变的。所以一般认为关系模式是相对稳定的,是模子。而关系是相对变化的,是值。

    其实这里的部分概念用关系数据库背后的数学来描述会更严谨一些,如关系就是笛卡尔积的子集,关系模式可以描述为R(U,D,DOM,F)等。不过本文不打算做细致讲解,只想对关系数据库做概述。

    接下来了解一下关系模型中的约束。
    约束,字面意思也清晰,就是限制,那限制啥呢?
    关系数据模型的操作主要包括查询、插入、删除和修改数据(常说的增删改查,CRUD)。约束就是来约束这些操作的,从而最终约束数据,约束整个关系(整张表)。也就是说,这些操作都要满足约束条件。
    约束的条件被称为关系的完整性约束,很明显,关系不是你想定义就定义的,它需要参照三种完整性的原则:

    1. 实体完整性:若属性A是基本关系R的主属性,那么A就不能取空值。所谓空值,就是无意义的值。比如说,学生(学号,姓名,年龄),那么学号就不能取空值,不然无意义。实体完整性,保证了该元组(记录)或者说实体的唯一性且可被标识
    2. 参照完整性:也称为引用完整性。定义上说过,关系模型中,实体与实体之间的联系都是用关系来表示的,这样就自然存在着关系与关系之间的引用。参照完整性要求关系中不允许引用不存在的实体。比如,现在有两张表(两个关系) 学生(学号,姓名,专业),专业(专业号,专业名)。
      学生表中,专业是外键。
    学号姓名专业
    1Lily计算机
    2Lyles扫地
    专业号专业名
    计算机1001
    软件工程1002

    显然扫地这个专业并不存在,就违反了参考完整性。

    1. 用户定义完整性:顾名思义,是由用户来定义的。也称为域完整性或语义完整性。它反映某一具体应用所涉及的数据必须知足的语义要求。比如,学生(学号,姓名,年龄)。
    学号姓名年龄
    1001Lily-1

    年龄这个字段应该是不能为负数的,这边显然不符合语义。


    三、结尾

    本文将关系数据库的由来,基本概念简单介绍了下。
    现在总结一下几个要点:

    • 广义数据库:存储数据的程序。狭义数据库:带有完善配套程序的数据库管理系统。
    • 关系数据库是基于关系模型的数据库,关系模型背后有一套数学理论支撑(主要是源于集合论)。
    • 关系数据模型是在关系结构的数据库中用二维表格的形式表示实体以及实体之间的联系的模型。
    • 关系数据库的一些基本概念。
  • 相关阅读:
    Linux中Java图片、二维码设置的中文变成乱码问题解决
    「运维有小邓」如何更有效的避免密码攻击
    stable diffusion图片转高清前后对比
    Python 集合
    Vue3 计算属性和侦听器实战(computed、watch)——简易点餐页面
    React -三种数据通信方法都怎么用?什么时候用?
    山东大学人工智能导论实验二 前向传播和反向传播
    vue组件的生命周期 笔记
    网络方向知识点梳理
    最优化方法Python计算:信赖域算法
  • 原文地址:https://blog.csdn.net/BadAyase/article/details/125533724