数据库导论
数据库管理系统在日常生活中的应用非常广泛,用于管理计算机数据。随着当今时代数据爆炸性增长,数据库系统也日益成为计算机应用的核心部分。
数据库是由一组模拟生活中某些方面的数据组织成的集合,例如,模拟学生或者歌曲库。数据库管理系统就是用于管理数据库的软件。
为什么引入数据库管理系统呢?
简易设计
假设我们用文件来管理数据库中的数据,以歌手和他们发布的专辑信息为例,我们将分别为歌手和专辑建立CSV文件。
歌手.csv
文件信息为
1 | "Wu Tang Clan",1992,"USA" |
每行的信息分别为歌手名、出道年份、国家。
专辑.csv
文件信息为
1 | "Enter the Wu Tang","Wu Tang Clan",1993 |
每行的信息分别为专辑名、歌手名、发布年份。
查询Ice Cube
出道年份可用如下代码实现:
1 | for line in file: |
但是这种通过文件来存储数据的方式存在不少问题
数据完整性
如何存储多个歌手的专辑信息?
如何防止无效信息的写入?
查询/更新实现
如何查询特定的记录?
如何实现基于同一数据库的应用?
如何控制线程并发写入数据库?
持久性
如何在机器更新时确保信息正确?
如何在多个设备之间同步?
基于以上考虑,我们引入了数据库管理系统,通过数据库管理系统来定义、创建、查询、更新数据库。
数据模型
接下来我们将通过数据模型来描述数据库中的数据。数据模型是数据库结构的基础。给定数据模型后,对特定数据集合的描述称为模式。
数据模型分为以下几类
关系模型 用表的集合来表示数据和数据建的联系
实体-联系模型 现实世界由一组称为实体的基本对象和这些对象之间的联系构成,实体-联系模型即用于描述这些数据。
半结构数据模型
网状数据模型
层次数据模型
其中网状数据模型和层次数据模型和底层实现很紧密,实现复杂,所以现在很少使用。数据库设计基本围绕关系模型展开。
关系模型
关系模型的核心在于
- 以简单的数据结构来存储数据(关系)
- 通过高级语言来操作数据
- 物理层存储取决于具体实现
关系模型主要由以下部分组成
- 结构:关系的定义和结构内容,即关系对应的属性和这些属性中的值
- 完整性:确保数据库内容满足约束,例如,所有的年份属性都应该是数字
- 操作:如何访问和修改数据库的内容
一个关系即是一组代表实体的属性的无序序列。正因为关系无序,所以数据库管理系统可以任何方式存储关系。一个有$n$个属性的关系被称为$n$列关系。
一个元组是关系中一组属性的值,也就是关系中某一行。元组中的值通常是原子的,即不可再拆分。特殊的空值NULL是每个域的成员。
一个关系的主键区别了不同的元组。某些数据库管理系统在用户未定义主键时自行创建主键。
数据库操纵语言
数据库系统提供数据定义语言来定义数据库模式,以及数据库操纵语言来表达数据库的管理和更新。实际上,数据定义和数据操作语言并不是分离的,而是简单地构成了单一的数据库语言的不同部分。
数据库操作语言分为两类
- 过程化数据库操纵语言 指明用户需要什么数据,以及怎么获取这些数据
- 声明化数据库操纵语言 只要求用户指定需要什么数据,而不指明如何获取这些数据
关系代数
关系代数是一个运算的集合,以一个或两个关系为输入,以一个新的关系为结果。可通过嵌套来实现更复杂的操作。
关系基本运算有:选择、投影、并、集合交、集合并、集合差、笛卡尔积和重命名。
选择运算
选择运算选出满足给定谓词的元组。
- 谓词过滤不符合条件的元组,仅留下满足谓词条件的元组
- 可通过连词将多个谓词连接
投影运算
投影运算以某个关系为输入,输出仅含特定属性的元组的关系。
- 可重新排列属性顺序
- 可对属性的值操作
集合交
集合交以两个关系为输入,输出仅含在两个关系中均出现的元组的关系。
集合并
集合并以两个关系为输入,输出在两个关系中至少出现一次的元组的关系。
集合差
集合并以两个关系为输入,输出在第一个关系中出现而第二个关系中不出现的元组的关系。
连接运算
以两个关系为输入,生成一个关系,该关系中的元组是两个元组(每个输入关系中各选一个)的组合,并且具有一个或多个属性的公共值。
笛卡尔积
以两个关系为输入,输出所有可能的组合。
关系代数为过程化语言,因为关系代数定义了计算查询的步骤。
例如,若想查询R和S连接后满足b_id等于102的元组,
关系代数可以是先连接R,S,再选择其中b_id等于102的元组,或者先选择S中b_id等于102的元组,再与R连接。
更好的方式是声明想让数据库管理系统返回的元组,类似查询R和S连接后满足b_id等于102的元组。
关系代数定义了数据库查询的原语。
关系模型仅描述了高层次的操作,与具体实现语言无关。