数据库数据模型详解
从概念模型到基本数据模型的完整解析
目录
- 前言
- [第一章 数据模型概述](#第一章 数据模型概述)
- [第二章 概念数据模型(E-R模型)](#第二章 概念数据模型(E-R模型))
- [第三章 层次模型](#第三章 层次模型)
- [第四章 网状模型](#第四章 网状模型)
- [第五章 关系模型](#第五章 关系模型)
- [第六章 面向对象模型](#第六章 面向对象模型)
- [第七章 数据模型的演进与对比](#第七章 数据模型的演进与对比)
- [第八章 实践应用与案例分析](#第八章 实践应用与案例分析)
- [第九章 面试与考试重点](#第九章 面试与考试重点)
- 总结
- 附录
前言
在学习数据库之前,我们首先要理解一个核心概念:数据模型。数据模型是数据库系统的灵魂,它决定了数据如何组织、如何操作、如何约束。可以说,理解了数据模型,就理解了数据库的本质。
什么是数据模型
数据模型的定义
**数据模型(Data Model)**是对现实世界数据特征的抽象,是用来描述数据、组织数据和对数据进行操作的一组概念和定义。
用一个生活中的类比来理解:
现实世界 数据模型 数据库
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ │ │ │ │ │
│ 建筑物 │ ────→ │ 建筑图纸 │ ────→ │ 实际房屋 │
│ (实体) │ │ (模型) │ │ (实现) │
│ │ │ │ │ │
└─────────────┘ └─────────────┘ └─────────────┘
就像建筑师用图纸来描述建筑一样,
数据库设计师用数据模型来描述数据的结构和关系。
更正式的定义:
数据模型是现实世界数据特征的模拟和抽象,是数据库系统的核心和基础。
数据模型的作用
数据模型在数据库系统中扮演着至关重要的角色:
数据模型的核心作用:
┌─────────────────────────────────────────────────────────────────┐
│ 数据模型的作用 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 描述作用 │
│ ├── 描述数据的静态特征(结构) │
│ ├── 描述数据的动态特征(操作) │
│ └── 描述数据的完整性约束 │
│ │
│ 2. 沟通作用 │
│ ├── 用户与设计者之间的沟通桥梁 │
│ ├── 业务需求到技术实现的转换工具 │
│ └── 不同角色之间的共同语言 │
│ │
│ 3. 指导作用 │
│ ├── 指导数据库的设计 │
│ ├── 指导应用程序的开发 │
│ └── 指导数据库的优化和维护 │
│ │
└─────────────────────────────────────────────────────────────────┘
数据模型与现实世界的关系
数据模型是连接现实世界和计算机世界的桥梁:
从现实世界到数据库的映射过程:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ 现实世界 │ ───→ │ 信息世界 │ ───→ │ 机器世界 │
│ (Real World) │ │ (Information │ │ (Computer │
│ │ │ World) │ │ World) │
│ │ │ │ │ │
├─────────────────┤ ├─────────────────┤ ├─────────────────┤
│ │ │ │ │ │
│ • 客观存在的事物│ │ • 实体 │ │ • 记录 │
│ • 事物的特征 │ │ • 属性 │ │ • 字段 │
│ • 事物间的联系 │ │ • 联系 │ │ • 表间关系 │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
│ │ │
▼ ▼ ▼
具体的人、物 概念数据模型 基本数据模型
(学生、课程) (E-R模型) (关系模型等)
举个例子:
| 现实世界 | 信息世界(E-R模型) | 机器世界(关系模型) |
|---|---|---|
| 一个学生张三 | 学生实体 | students表中的一行记录 |
| 学生的姓名 | name属性 | name字段 |
| 学生选课 | 选课联系 | 选课表+外键关系 |
数据模型的分类
按照抽象程度和用途,数据模型可以分为两大类:
数据模型分类体系:
┌─────────────────────────────────────┐
│ 数据模型 │
└─────────────────────────────────────┘
│
┌───────────────────────┴───────────────────────┐
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ 概念数据模型 │ │ 基本数据模型 │
│ (Conceptual Model) │ │ (Basic Model) │
├─────────────────────┤ ├─────────────────────┤
│ │ │ │
│ • E-R模型 │ │ • 层次模型 │
│ • 面向用户 │ │ • 网状模型 │
│ • 用于需求分析 │ │ • 关系模型 │
│ • 独立于DBMS │ │ • 面向对象模型 │
│ │ │ • 面向计算机实现 │
└─────────────────────┘ └─────────────────────┘
概念数据模型(Conceptual Data Model)
概念数据模型 是按照用户的观点来对数据和信息建模,主要用于数据库设计阶段。
- 代表:E-R模型(实体---联系模型)
- 特点 :
-
独立于具体的DBMS
-
强调语义表达
-
用于与用户沟通需求
-
是从现实世界到机器世界的中间层
概念模型的定位:
用户/业务人员 ←──→ 概念数据模型 ←──→ 数据库设计师
↑ │ │
│ │ │
理解业务 E-R图 转换为逻辑模型
-
基本数据模型(Logical/Physical Data Model)
基本数据模型 (也称结构数据模型)是按照计算机系统的观点对数据建模,用于DBMS的实现。
主要包括四种经典模型:
| 模型类型 | 数据结构 | 代表产品 | 时代 |
|---|---|---|---|
| 层次模型 | 树形结构 | IBM IMS | 1960s |
| 网状模型 | 图形结构 | IDMS, DBTG | 1970s |
| 关系模型 | 表格结构 | Oracle, MySQL | 1970s-至今 |
| 面向对象模型 | 对象结构 | ObjectDB | 1990s |
数据模型的三要素
任何一个数据模型都包含三个要素,这是理解数据模型的关键:
数据模型的三要素:
┌─────────────────────────────────────────────────────────────────┐
│ 数据模型 = 结构 + 操作 + 约束 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. 数据结构(Data Structure) │ │
│ │ 描述数据的静态特征 │ │
│ │ • 数据对象的类型 │ │
│ │ • 数据对象的内容 │ │
│ │ • 数据对象之间的联系 │ │
│ │ 类比:建筑的框架结构 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 2. 数据操作(Data Operation) │ │
│ │ 描述数据的动态特征 │ │
│ │ • 查询(Query) │ │
│ │ • 更新(Update):插入、删除、修改 │ │
│ │ 类比:建筑的使用方式 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 3. 数据约束(Data Constraint) │ │
│ │ 描述数据的完整性规则 │ │
│ │ • 数据的取值范围 │ │
│ │ • 数据之间的依赖关系 │ │
│ │ • 数据的一致性要求 │ │
│ │ 类比:建筑的安全规范 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
以关系模型为例说明三要素:
sql
-- 数据结构:表的定义
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
age INT,
email VARCHAR(100) UNIQUE
);
-- 数据操作:增删改查
INSERT INTO students VALUES (1, '张三', 20, 'zhangsan@example.com');
SELECT * FROM students WHERE age > 18;
UPDATE students SET age = 21 WHERE id = 1;
DELETE FROM students WHERE id = 1;
-- 数据约束:完整性规则
-- PRIMARY KEY: 主键约束,保证唯一性
-- NOT NULL: 非空约束
-- UNIQUE: 唯一约束
-- CHECK (age > 0 AND age < 150): 检查约束
第一章 数据模型概述
1.1 数据模型的基本概念
数据模型的定义与内涵
**数据模型(Data Model)**的完整定义包含以下几个层面:
数据模型的多层理解:
┌─────────────────────────────────────────────────────────────────┐
│ 数据模型的内涵 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 技术层面: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 数据模型是数据库中数据的存储方式及其相互联系的逻辑表示 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 语义层面: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 数据模型是对现实世界的数据及其联系的形式化描述 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 应用层面: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 数据模型是用户与数据库之间沟通的工具和桥梁 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
数据模型的本质:是一种抽象,把复杂的现实世界简化为计算机能够处理的形式。
数据模型在数据库系统中的地位
数据模型是数据库系统的核心和基础:
数据模型在数据库系统中的地位:
┌─────────────────────────────┐
│ 用户/应用程序 │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ DBMS │
│ ┌─────────────────────┐ │
│ │ 数据模型 │ │ ← 核心!
│ │ ┌───────────────┐ │ │
│ │ │ 数据结构 │ │ │
│ │ │ 数据操作 │ │ │
│ │ │ 数据约束 │ │ │
│ │ └───────────────┘ │ │
│ └─────────────────────┘ │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ 数据库 │
│ (物理存储) │
└─────────────────────────────┘
数据模型决定了:
• DBMS如何组织数据
• DBMS提供什么操作
• DBMS如何保证数据完整性
数据模型的发展历程
数据模型的发展经历了几个重要阶段:
数据模型发展时间线:
1960s 1970s 1980s 1990s 2000s+
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐
│层次│ → │网状│ → │关系│ → │OO/ │ → │NoSQL│
│模型│ │模型│ │模型│ │OR │ │多模型│
└────┘ └────┘ └────┘ └────┘ └────┘
│ │ │ │ │
IBM IMS CODASYL E.F.Codd OODBMS MongoDB
(1968) DBTG (1970) Neo4j
(1971) Redis
关键里程碑:
• 1968年:IBM发布IMS,层次模型商用化
• 1970年:Codd发表关系模型论文,数据库理论革命
• 1976年:Peter Chen提出E-R模型
• 1986年:SQL成为ISO标准
• 2000s:NoSQL运动兴起,多模型并存
1.2 数据模型的分类体系
按抽象层次分类
数据模型可以按照抽象程度分为三个层次:
数据模型的三个抽象层次:
┌─────────────────────────────────────────────────────────────────┐
│ 抽象层次 模型类型 面向对象 示例 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 高层/概念层 概念数据模型 业务用户 E-R模型 │ │
│ │ (Conceptual) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ 转换 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 中层/逻辑层 逻辑数据模型 数据库设计者 关系模型 │ │
│ │ (Logical) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ 映射 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 低层/物理层 物理数据模型 系统管理员 存储结构 │ │
│ │ (Physical) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
三层模型的详细对比:
| 层次 | 概念层 | 逻辑层 | 物理层 |
|---|---|---|---|
| 目的 | 描述业务需求 | 描述数据结构 | 描述存储方式 |
| 面向 | 业务人员、用户 | 数据库设计者 | DBA、系统管理员 |
| 独立性 | 独立于DBMS | 依赖于数据模型类型 | 依赖于具体DBMS |
| 示例 | E-R图 | 表结构定义 | 索引、分区、存储 |
| 工具 | PowerDesigner、Visio | SQL DDL | 数据库配置 |
按数据结构分类
按照数据的组织结构,基本数据模型分为四种:
四种基本数据模型的结构对比:
┌────────────────────────────────────────────────────────────────┐
│ │
│ 层次模型(树形) 网状模型(图形) │
│ │
│ [A] [A]───────[B] │
│ / │ \ │\ /│ │
│ [B][C][D] │ \ / │ │
│ /\ │ \ / │ │
│ [E][F] [C]──[D]──[E] │
│ │
│ • 一个父节点 • 可以有多个父节点 │
│ • 只能表示1:N关系 • 可以表示M:N关系 │
│ │
├────────────────────────────────────────────────────────────────┤
│ │
│ 关系模型(表格) 面向对象模型 │
│ │
│ ┌────┬────┬────┐ ┌─────────────────┐ │
│ │ ID │Name│Age │ │ Person │ │
│ ├────┼────┼────┤ │ ───────────────│ │
│ │ 1 │张三│ 20 │ │ -name: String │ │
│ │ 2 │李四│ 22 │ │ -age: int │ │
│ └────┴────┴────┘ │ +getName() │ │
│ │ +setAge() │ │
│ • 二维表格结构 └─────────────────┘ │
│ • 关系代数基础 • 封装+继承+多态 │
│ │
└────────────────────────────────────────────────────────────────┘
四种模型的特点总结:
| 模型 | 结构 | 优点 | 缺点 | 典型应用 |
|---|---|---|---|---|
| 层次模型 | 树形 | 简单、高效 | 灵活性差 | 银行、航空(历史系统) |
| 网状模型 | 图形 | 灵活、表达力强 | 复杂、难维护 | 制造业(历史系统) |
| 关系模型 | 表格 | 简洁、理论完善 | 性能开销 | 企业应用、Web应用 |
| 面向对象 | 对象 | 表达复杂数据 | 标准不统一 | CAD、多媒体 |
1.3 数据模型的三要素详解
数据结构:描述数据的静态特征
数据结构是数据模型最重要的组成部分,它决定了数据如何组织:
不同模型的数据结构对比:
┌─────────────────────────────────────────────────────────────────┐
│ 数据结构对比 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ E-R模型的数据结构: │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 实体 │──────│ 联系 │──────│ 属性 │ │
│ │ Entity │ │Relation │ │Attribute│ │
│ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ 关系模型的数据结构: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 关系(表) = 元组(行) + 属性(列) + 域 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 面向对象模型的数据结构: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 类 = 属性 + 方法 (继承、组合等关系) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
数据操作:描述数据的动态特征
数据操作定义了可以对数据执行的操作类型:
各模型的操作方式对比:
┌─────────────────────────────────────────────────────────────────┐
│ 模型 操作方式 操作特点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 层次模型 导航式访问 必须从根节点开始,逐层访问 │
│ (Navigation) 需要知道数据的层次路径 │
│ │
│ 网状模型 导航式访问 通过链接指针遍历 │
│ (Navigation) 需要知道数据的连接路径 │
│ │
│ 关系模型 集合式操作 声明式操作(说明要什么) │
│ (Set-at-a-time) 不需要知道数据的存储路径 │
│ SQL语言 │
│ │
│ OO模型 方法调用 通过对象的方法操作数据 │
│ (Method Call) 封装了数据访问逻辑 │
│ │
└─────────────────────────────────────────────────────────────────┘
操作方式的演进:
导航式(低级) → 集合式(高级) → 声明式(更高级)
"怎么找数据" "操作一组数据" "我要什么数据"
SQL vs 导航式操作的对比:
sql
-- 关系模型:集合式操作(声明式)
SELECT name, age FROM students WHERE age > 20;
-- 一条语句操作所有符合条件的记录
-- 层次模型:导航式操作(过程式,伪代码)
GET UNIQUE student -- 获取根节点
DO WHILE status = 0
IF age > 20 THEN
PRINT name, age
END IF
GET NEXT student -- 获取下一个节点
END DO
-- 需要逐条遍历,逻辑复杂
数据约束:描述数据的完整性规则
数据约束保证数据的正确性和一致性:
数据约束的分类:
┌─────────────────────────────────────────────────────────────────┐
│ 数据约束类型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 实体完整性约束(Entity Integrity) │
│ ├── 主键不能为空 │
│ ├── 主键必须唯一 │
│ └── 每个实体必须可以被唯一标识 │
│ │
│ 2. 参照完整性约束(Referential Integrity) │
│ ├── 外键要么为空,要么引用有效的主键 │
│ ├── 删除被引用记录时需要处理引用记录 │
│ └── 保证实体间联系的正确性 │
│ │
│ 3. 用户定义完整性约束(User-defined Integrity) │
│ ├── 取值范围约束(如:年龄 > 0) │
│ ├── 格式约束(如:邮箱格式) │
│ └── 业务规则约束(如:余额 >= 0) │
│ │
└─────────────────────────────────────────────────────────────────┘
约束的SQL实现示例:
sql
CREATE TABLE students (
-- 实体完整性:主键约束
id INT PRIMARY KEY,
-- 用户定义约束:非空
name VARCHAR(50) NOT NULL,
-- 用户定义约束:检查约束
age INT CHECK (age > 0 AND age < 150),
-- 用户定义约束:唯一约束
email VARCHAR(100) UNIQUE,
-- 参照完整性:外键约束
class_id INT,
FOREIGN KEY (class_id) REFERENCES classes(id)
ON DELETE SET NULL
ON UPDATE CASCADE
);
1.4 现实世界到数据库的抽象过程
现实世界 → 信息世界 → 机器世界
数据库的设计本质上是一个抽象的过程:
数据抽象的三个世界:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 第一步:现实世界 → 信息世界 │
│ ──────────────────────────────── │
│ │
│ 现实世界 信息世界 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 具体的人: │ │ 学生实体: │ │
│ │ 张三,20岁 │ ──────→ │ 姓名:张三 │ │
│ │ 计算机专业 │ (抽象) │ 年龄:20 │ │
│ │ 学号2024001 │ │ 专业:计算机 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ 抽取事物的特征,忽略不重要的细节 │
│ 使用 E-R 模型进行描述 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 第二步:信息世界 → 机器世界 │
│ ──────────────────────────────── │
│ │
│ 信息世界 机器世界 │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 学生实体: │ │ students表: │ │
│ │ 姓名、年龄、专业│ ──────→ │ id, name, age, │ │
│ │ │ (转换) │ major │ │
│ │ 选课联系 │ │ enrollments表 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ 将概念模型转换为具体的数据库结构 │
│ 使用关系模型等逻辑模型实现 │
│ │
└─────────────────────────────────────────────────────────────────┘
概念模型的桥梁作用
概念模型(E-R模型)在这个过程中起着关键的桥梁作用:
E-R模型的桥梁作用:
用户需求 数据库实现
│ ▲
▼ │
┌─────────────────┐ ┌─────────────────┐
│ │ │ │
│ "我需要管理 │ │ CREATE TABLE │
│ 学生选课" │ │ students (..); │
│ │ │ CREATE TABLE │
│ │ │ courses (..); │
│ │ │ │
└─────────────────┘ └─────────────────┘
│ ▲
│ E-R模型(桥梁) │
│ ┌─────────────────────┐ │
└──→ │ │ ───────────┘
│ ┌───────┐ │
│ │ 学生 │ │
│ └───┬───┘ │
│ │ 选课 │
│ ┌───┴───┐ │
│ │ 课程 │ │
│ └───────┘ │
│ │
└─────────────────────┘
作用:
• 业务人员能看懂
• 技术人员能实现
• 双方可以沟通确认
抽象过程示例
以一个简单的图书馆系统为例:
图书馆系统的抽象过程:
【现实世界】
┌─────────────────────────────────────────────────────────────────┐
│ • 读者张三来图书馆,用身份证办理借书证 │
│ • 张三在书架上找到《数据库原理》这本书 │
│ • 张三把书拿到柜台,图书管理员刷借书证,登记借书 │
│ • 系统记录:张三借了《数据库原理》,应还日期12月1日 │
└─────────────────────────────────────────────────────────────────┘
│
▼ 抽象
【信息世界 - E-R模型】
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────┐ │
│ │ 读者姓名 │ │
│ └────┬─────┘ │
│ ┌───────┴───────┐ │
│ │ 读者 │ │
│ └───────┬───────┘ │
│ │ │
│ │ 借阅 ───── 借阅日期、应还日期 │
│ │ │
│ ┌───────┴───────┐ │
│ │ 图书 │ │
│ └───────┬───────┘ │
│ ┌───────┴───────┐ │
│ │ 书名、ISBN │ │
│ └───────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
│
▼ 转换
【机器世界 - 关系模型】
┌─────────────────────────────────────────────────────────────────┐
│ │
│ CREATE TABLE readers ( │
│ reader_id INT PRIMARY KEY, │
│ name VARCHAR(50) NOT NULL, │
│ id_card VARCHAR(20) UNIQUE │
│ ); │
│ │
│ CREATE TABLE books ( │
│ book_id INT PRIMARY KEY, │
│ title VARCHAR(200) NOT NULL, │
│ isbn VARCHAR(20) UNIQUE │
│ ); │
│ │
│ CREATE TABLE borrows ( │
│ borrow_id INT PRIMARY KEY, │
│ reader_id INT REFERENCES readers(reader_id), │
│ book_id INT REFERENCES books(book_id), │
│ borrow_date DATE NOT NULL, │
│ due_date DATE NOT NULL │
│ ); │
│ │
└─────────────────────────────────────────────────────────────────┘
抽象过程的关键原则:
| 原则 | 说明 | 示例 |
|---|---|---|
| 取舍 | 只保留相关特征 | 读者的身高体重不需要 |
| 分类 | 相似事物归为一类 | 所有读者归为"读者"实体 |
| 概括 | 抽取共同特征 | 所有图书都有书名、ISBN |
| 关联 | 建立事物间联系 | 读者与图书通过"借阅"联系 |
第二章 概念数据模型(E-R模型)
概念数据模型是数据库设计的第一步,它用一种直观的方式描述现实世界的数据及其联系。在所有概念数据模型中,**E-R模型(Entity-Relationship Model,实体-联系模型)**是最经典、最广泛使用的一种。
2.1 E-R模型概述
E-R模型的起源
E-R模型 由美籍华人计算机科学家陈品山(Peter Chen)于1976年在论文《The Entity-Relationship Model---Toward a Unified View of Data》中首次提出。
E-R模型的历史背景:
┌─────────────────────────────────────────────────────────────────┐
│ E-R模型诞生背景 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 时间:1976年 │
│ 提出者:Peter Chen(陈品山) │
│ 发表于:ACM Transactions on Database Systems │
│ │
│ 背景问题: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 层次模型和网状模型过于技术化,用户难以理解 │ │
│ │ • 关系模型刚提出,缺乏直观的设计方法 │ │
│ │ • 需要一种用户和设计者都能理解的"通用语言" │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 解决方案:E-R模型 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 用"实体"表示现实世界的事物 │ │
│ │ • 用"联系"表示事物之间的关系 │ │
│ │ • 用"属性"描述事物的特征 │ │
│ │ • 用图形化的E-R图直观展示 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Peter Chen的贡献:
| 贡献点 | 说明 |
|---|---|
| 统一视图 | 提供了一种独立于任何DBMS的数据描述方法 |
| 图形表示 | 发明了E-R图,使数据模型可视化 |
| 语义丰富 | 强调数据的语义,而不仅仅是结构 |
| 设计方法 | 为数据库设计提供了系统的方法论 |
E-R模型的基本思想
E-R模型的核心思想非常简单:用实体、属性和联系来描述现实世界。
E-R模型的核心思想:
现实世界
│
▼
┌───────────────────────────────────────────┐
│ E-R模型的视角 │
├───────────────────────────────────────────┤
│ │
│ 现实世界中存在着: │
│ │
│ ┌─────────┐ │
│ │ 事物 │ ────→ 实体(Entity) │
│ └─────────┘ │
│ │ │
│ │ 具有 │
│ ▼ │
│ ┌─────────┐ │
│ │ 特征 │ ────→ 属性(Attribute) │
│ └─────────┘ │
│ │ │
│ │ 之间存在 │
│ ▼ │
│ ┌─────────┐ │
│ │ 关系 │ ────→ 联系(Relationship) │
│ └─────────┘ │
│ │
└───────────────────────────────────────────┘
用一个简单例子理解E-R模型:
现实场景:学生选课
现实世界描述:
"学生张三选修了数据库课程,成绩是90分"
E-R模型分析:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ┌──────────┐ │
│ │ 姓名 │ │
│ └────┬─────┘ │
│ │ │
│ ┌──────────┐ ┌─────┴─────┐ ┌──────────┐ │
│ │ 学号 │────│ 学生 │────│ 年龄 │ │
│ └──────────┘ └─────┬─────┘ └──────────┘ │
│ │ │
│ │ 选修 │
│ │ │
│ ┌──────────┐ ┌─────┴─────┐ ┌──────────┐ │
│ │ 成绩 │────│ 选课 │ │
│ └──────────┘ └─────┬─────┘ │
│ │ │
│ │ │
│ ┌──────────┐ ┌─────┴─────┐ ┌──────────┐ │
│ │ 课程号 │────│ 课程 │────│ 课程名 │ │
│ └──────────┘ └───────────┘ └──────────┘ │
│ │
│ 实体:学生、课程 │
│ 联系:选修(多对多) │
│ 属性:学号、姓名、年龄、课程号、课程名、成绩 │
│ │
└─────────────────────────────────────────────────────────────────┘
E-R模型的三个核心概念:
| 概念 | 英文 | 含义 | 图形符号 |
|---|---|---|---|
| 实体 | Entity | 现实世界中可以区分的事物 | 矩形 □ |
| 属性 | Attribute | 实体的特征或性质 | 椭圆 ○ |
| 联系 | Relationship | 实体之间的关联 | 菱形 ◇ |
E-R模型的应用场景
E-R模型在实际工作中有广泛的应用:
E-R模型的应用场景:
┌─────────────────────────────────────────────────────────────────┐
│ E-R模型的应用 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 需求分析阶段 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 与用户沟通,理解业务需求 │ │
│ │ • 识别系统中的核心实体 │ │
│ │ • 明确实体之间的业务关系 │ │
│ │ • 形成需求文档的一部分 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 概念设计阶段 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 设计概念模型(E-R图) │ │
│ │ • 独立于任何DBMS │ │
│ │ • 作为后续逻辑设计的基础 │ │
│ │ • 便于需求评审和确认 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 逻辑设计阶段 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 将E-R图转换为关系模型 │ │
│ │ • 实体 → 表 │ │
│ │ • 属性 → 字段 │ │
│ │ • 联系 → 外键或关联表 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4. 文档与沟通 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 技术文档的核心组成部分 │ │
│ │ • 开发团队之间的沟通工具 │ │
│ │ • 新成员快速理解系统的途径 │ │
│ │ • 系统维护和升级的参考 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
E-R模型在数据库设计流程中的位置:
数据库设计流程:
┌──────────────┐
│ 需求分析 │ ← 收集用户需求,了解业务规则
└──────┬───────┘
│
▼
┌──────────────┐
│ 概念设计 │ ← E-R模型在此阶段使用 ⭐
│ (E-R图) │
└──────┬───────┘
│ 转换
▼
┌──────────────┐
│ 逻辑设计 │ ← 转换为关系模型(表结构)
└──────┬───────┘
│
▼
┌──────────────┐
│ 物理设计 │ ← 确定索引、分区、存储
└──────┬───────┘
│
▼
┌──────────────┐
│ 实施运维 │ ← 创建数据库,部署运行
└──────────────┘
E-R模型的优势总结:
| 优势 | 说明 |
|---|---|
| 直观易懂 | 图形化表示,业务人员也能理解 |
| 独立性强 | 不依赖于任何特定的DBMS |
| 语义丰富 | 能够表达复杂的业务规则和约束 |
| 标准通用 | 业界广泛接受的标准方法 |
| 便于沟通 | 作为技术人员和业务人员的共同语言 |
| 易于转换 | 有成熟的方法转换为关系模型 |
2.2 E-R模型的基本元素
E-R模型由三个核心元素组成:实体(Entity) 、属性(Attribute)和联系(Relationship)。掌握这三个概念是理解和使用E-R模型的基础。
2.2.1 实体(Entity)
实体的定义
**实体(Entity)**是现实世界中可以区别于其他对象的"事物"或"对象"。实体可以是具体的,也可以是抽象的。
实体的分类:
┌─────────────────────────────────────────────────────────────────┐
│ 实体的类型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 具体实体(有形) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 人:学生、教师、员工、客户 │ │
│ │ • 物:书籍、商品、设备、车辆 │ │
│ │ • 地点:教室、仓库、城市 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 抽象实体(无形) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 事件:订单、借阅、选课、考试 │ │
│ │ • 概念:课程、职位、角色、权限 │ │
│ │ • 状态:账户余额、库存状态 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
判断是否为实体的标准:
| 标准 | 说明 | 示例 |
|---|---|---|
| 可区分性 | 能够与其他事物区分开 | 每个学生有唯一学号 |
| 有意义 | 对业务有实际意义 | "学生"是管理对象 |
| 有属性 | 具有可描述的特征 | 学生有姓名、年龄等 |
| 可存储 | 需要在数据库中保存 | 学生信息需要持久化 |
实体集的概念
**实体集(Entity Set)**是具有相同类型和属性的实体的集合。
实体与实体集的关系:
实体集(类型) 实体(实例)
┌─────────────┐ ┌─────────────────────────┐
│ │ │ │
│ 学生 │ ───包含───→ │ 张三(学号:001) │
│ (Student) │ │ 李四(学号:002) │
│ │ │ 王五(学号:003) │
│ │ │ ... │
└─────────────┘ └─────────────────────────┘
类比:
• 实体集 ≈ 类(Class)
• 实体 ≈ 对象/实例(Object/Instance)
• 实体集 ≈ 表(Table)
• 实体 ≈ 行/记录(Row/Record)
强实体与弱实体
根据实体是否能独立存在,可分为强实体和弱实体:
强实体与弱实体的对比:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 强实体(Strong Entity) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 可以独立存在,不依赖其他实体 │ │
│ │ • 有自己的主键(关键属性) │ │
│ │ • 示例:学生、课程、部门、员工 │ │
│ │ │ │
│ │ 图形表示:单线矩形 │ │
│ │ ┌─────────┐ │ │
│ │ │ 学生 │ │ │
│ │ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 弱实体(Weak Entity) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 依赖于其他实体(所有者实体)才能存在 │ │
│ │ • 没有自己的完整主键,需要借助所有者的键 │ │
│ │ • 示例:订单明细(依赖订单)、家属(依赖员工) │ │
│ │ │ │
│ │ 图形表示:双线矩形 │ │
│ │ ╔═════════╗ │ │
│ │ ║订单明细 ║ │ │
│ │ ╚═════════╝ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
弱实体的实例:
订单与订单明细的关系:
┌─────────────┐ ╔═════════════╗
│ 订单 │ ║ 订单明细 ║
│ (强实体) │ ←─包含─→ ║ (弱实体) ║
└─────────────┘ ╚═════════════╝
│ │
│ 订单号(PK) │ 订单号(FK) + 行号
│ 订单日期 │ 商品ID
│ 客户ID │ 数量
│ 总金额 │ 单价
弱实体"订单明细"依赖于强实体"订单":
• 没有订单就不会有订单明细
• 主键 = 订单号 + 行号(部分依赖订单的键)
实体的图形表示
E-R图中实体的表示方法:
强实体:单线矩形
┌─────────────┐
│ 学生 │
└─────────────┘
弱实体:双线矩形
╔═════════════╗
║ 家属 ║
╚═════════════╝
在矩形内部写实体名称(通常用名词)
2.2.2 属性(Attribute)
属性的定义
**属性(Attribute)**是实体所具有的某一特性,用来描述实体的特征。
属性的作用:
实体 属性
┌─────────────┐ ┌─────────────────────────┐
│ │ │ │
│ 学生 │ ───具有───→ │ 学号 │
│ │ │ 姓名 │
│ │ │ 性别 │
│ │ │ 出生日期 │
│ │ │ Email │
│ │ │ ... │
└─────────────┘ └─────────────────────────┘
属性的作用:
• 描述实体的特征
• 区分不同的实体实例
• 存储实体的具体数据
属性的分类
属性可以从多个维度进行分类:
属性的分类体系:
┌─────────────────────────────────────────────────────────────────┐
│ 属性的分类 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 按结构分类 │
│ ├── 简单属性(Simple):不可再分 │
│ │ 例:年龄、性别、学号 │
│ └── 复合属性(Composite):可再分为更小的属性 │
│ 例:地址 = 省 + 市 + 区 + 街道 │
│ │
│ 2. 按值的个数分类 │
│ ├── 单值属性(Single-valued):只有一个值 │
│ │ 例:身份证号(每人只有一个) │
│ └── 多值属性(Multi-valued):可以有多个值 │
│ 例:电话号码(一人可有多个) │
│ │
│ 3. 按是否存储分类 │
│ ├── 存储属性(Stored):直接存储在数据库中 │
│ │ 例:出生日期 │
│ └── 派生属性(Derived):从其他属性计算得出 │
│ 例:年龄(从出生日期计算) │
│ │
│ 4. 按是否可空分类 │
│ ├── 非空属性:必须有值 │
│ │ 例:学号、姓名 │
│ └── 可空属性:可以为空 │
│ 例:中间名(有些人没有) │
│ │
└─────────────────────────────────────────────────────────────────┘
各类属性的详细说明和图形表示:
属性类型的图形表示:
1. 简单属性 vs 复合属性
简单属性: 复合属性:
┌──────┐ ┌──────┐
│ 年龄 │ │ 地址 │
└──────┘ └───┬──┘
┌────┼────┐
┌┴┐ ┌┴┐ ┌┴┐
│省│ │市│ │街道│
└─┘ └─┘ └───┘
2. 单值属性 vs 多值属性
单值属性: 多值属性(双线椭圆):
┌──────────┐ ╔══════════╗
│ 身份证号 │ ║ 电话号码 ║
└──────────┘ ╚══════════╝
3. 存储属性 vs 派生属性
存储属性: 派生属性(虚线椭圆):
┌──────────┐ ┌ ─ ─ ─ ─ ─┐
│ 出生日期 │ │ 年龄 │
└──────────┘ └ ─ ─ ─ ─ ─┘
关键属性(Key Attribute)
**关键属性(Key Attribute)**是能够唯一标识实体的属性或属性组合。
关键属性的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 关键属性类型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 超键(Super Key) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 能唯一标识实体的属性或属性组合 │ │
│ │ 例:{学号}、{学号,姓名}、{身份证号}都是超键 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 候选键(Candidate Key) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 最小的超键(不包含多余属性) │ │
│ │ 例:{学号}、{身份证号}是候选键 │ │
│ │ {学号,姓名}不是候选键(姓名多余) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 主键(Primary Key) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 从候选键中选择一个作为主键 │ │
│ │ 例:选择{学号}作为学生的主键 │ │
│ │ │ │
│ │ 图形表示:下划线 │ │
│ │ ┌─────────┐ │ │
│ │ │ _学号_ │ ← 下划线表示主键 │ │
│ │ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
属性的图形表示
E-R图中属性的完整表示:
┌──────────┐
│ _学号_ │ ← 主键属性(下划线)
└────┬─────┘
┌────────────────┼────────────────┐
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ 姓名 │ │ 性别 │ │ 出生日期│
└─────────┘ └─────────┘ └────┬────┘
│
┌ ─ ─ ┴ ─ ─┐
│ 年龄 │ ← 派生属性(虚线)
└ ─ ─ ─ ─ ─┘
│
┌────┴────┐
│ │
╔═══════════╗ ┌─────────┐
║ 联系电话 ║ │ 地址 │ ← 复合属性
╚═══════════╝ └────┬────┘
↑ ┌────┼────┐
多值属性 ┌┴┐ ┌┴┐ ┌┴┐
(双线椭圆) │省│ │市│ │街│
└─┘ └─┘ └─┘
2.2.3 联系(Relationship)
联系的定义
**联系(Relationship)**是实体之间的关联关系,表示实体之间有意义的关联。
联系的本质:
┌─────────────────────────────────────────────────────────────────┐
│ 联系的理解 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 现实世界 E-R模型 │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ │ │ │ │
│ │ "学生 选修 课程" │ ───→ │ 学生 ──选修── 课程 │ │
│ │ "员工 属于 部门" │ ───→ │ 员工 ──属于── 部门 │ │
│ │ "作者 撰写 书籍" │ ───→ │ 作者 ──撰写── 书籍 │ │
│ │ │ │ │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
│ │
│ 联系通常用动词来命名 │
│ │
└─────────────────────────────────────────────────────────────────┘
联系的类型
联系按照参与的实体个数 和映射基数分类:
按参与实体个数分类:
联系的度(Degree):
1. 一元联系(递归联系):同一实体集内的联系
┌─────────────────────────────────────────┐
│ │
│ ┌─────────┐ │
│ │ 员工 │──┐ │
│ └─────────┘ │ 管理 │
│ ▲ │ │
│ └───────┘ │
│ │
│ 员工管理员工(上下级关系) │
└─────────────────────────────────────────┘
2. 二元联系:两个不同实体集之间的联系(最常见)
┌─────────────────────────────────────────┐
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ 学生 │───选修────│ 课程 │ │
│ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────┘
3. 三元联系:三个实体集之间的联系
┌─────────────────────────────────────────┐
│ │
│ ┌─────────┐ │
│ │ 供应商 │ │
│ └────┬────┘ │
│ │ │
│ ┌─────────┐│┌─────────┐ │
│ │ 项目 │┴││ 零件 │ │
│ └─────────┘ └─────────┘ │
│ │
│ 供应商为项目供应零件 │
└─────────────────────────────────────────┘
按映射基数分类(最重要):
联系的映射基数(Cardinality):
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 1. 一对一联系(1:1) │
│ ───────────────────── │
│ 一个A实体最多对应一个B实体,反之亦然 │
│ │
│ ┌────────┐ 1 1 ┌────────┐ │
│ │ 员工 │──────────◇──────────│ 工位 │ │
│ └────────┘ 分配 └────────┘ │
│ │
│ 示例:一个员工分配一个工位,一个工位只能分给一个员工 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 2. 一对多联系(1:N) │
│ ───────────────────── │
│ 一个A实体对应多个B实体,但一个B实体只对应一个A实体 │
│ │
│ ┌────────┐ 1 N ┌────────┐ │
│ │ 部门 │──────────◇──────────│ 员工 │ │
│ └────────┘ 包含 └────────┘ │
│ │
│ 示例:一个部门有多个员工,但一个员工只属于一个部门 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 3. 多对多联系(M:N) │
│ ───────────────────── │
│ 一个A实体对应多个B实体,一个B实体也对应多个A实体 │
│ │
│ ┌────────┐ M N ┌────────┐ │
│ │ 学生 │──────────◇──────────│ 课程 │ │
│ └────────┘ 选修 └────────┘ │
│ │
│ 示例:一个学生选多门课,一门课被多个学生选 │
│ │
└─────────────────────────────────────────────────────────────────┘
常见联系类型的实例:
| 联系类型 | 实例1 | 实例2 | 实例3 |
|---|---|---|---|
| 1:1 | 人-身份证 | 国家-首都 | 丈夫-妻子 |
| 1:N | 班级-学生 | 母亲-孩子 | 订单-订单明细 |
| M:N | 学生-课程 | 作者-书籍 | 医生-患者 |
联系的属性
联系本身也可以有属性,称为联系属性:
联系属性的示例:
学生选修课程的场景:
┌────────┐ ┌────────┐ ┌────────┐
│ _学号_ │ │ 成绩 │ │_课程号_│
└───┬────┘ └───┬────┘ └───┬────┘
│ ┌─────────────┴─────────────┐ │
│ │ 选修时间 │ │
│ └─────────────┬─────────────┘ │
│ │ │
┌───┴────┐ ┌─────┴─────┐ ┌───┴────┐
│ 学生 │─────────│ 选修 │─────────│ 课程 │
└────────┘ M └───────────┘ N └────────┘
联系"选修"的属性:
• 成绩:某学生选某课程的成绩
• 选修时间:选课的时间
这些属性既不属于学生,也不属于课程,
而是属于"选修"这个联系本身。
联系的图形表示
E-R图中联系的表示:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 基本联系:菱形 │
│ │
│ ┌─────────┐ ◇ ┌─────────┐ │
│ │ 实体A │─────────◇───────────│ 实体B │ │
│ └─────────┘ 选修 └─────────┘ │
│ │
│ 弱实体的联系:双线菱形 │
│ │
│ ┌─────────┐ ◈ ╔═════════╗ │
│ │ 订单 │─────────◈───────────║订单明细 ║ │
│ └─────────┘ 包含 ╚═════════╝ │
│ │
│ 带属性的联系: │
│ ┌──────┐ │
│ │ 成绩 │ │
│ └───┬──┘ │
│ │ │
│ ┌─────────┐ ◇───┘ ┌─────────┐ │
│ │ 学生 │─────────◇───────────│ 课程 │ │
│ └─────────┘ 选修 └─────────┘ │
│ │
│ 标注基数: │
│ │
│ ┌─────────┐ 1 N ┌─────────┐ │
│ │ 部门 │─────────◇───────────│ 员工 │ │
│ └─────────┘ 包含 └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
参与约束
实体参与联系的方式还可以分为全部参与 和部分参与:
参与约束:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 全部参与(Total Participation): │
│ 每个实体都必须参与联系 │
│ │
│ ┌─────────┐ ═══════════◇═══════════ ┌─────────┐ │
│ │ 员工 │═══════════════════════════│ 部门 │ │
│ └─────────┘ 属于 └─────────┘ │
│ ↑ │
│ 双线表示全部参与:每个员工都必须属于某个部门 │
│ │
│ 部分参与(Partial Participation): │
│ 不是每个实体都必须参与联系 │
│ │
│ ┌─────────┐ ───────────◇─────────── ┌─────────┐ │
│ │ 员工 │─────────────────────────│ 项目 │ │
│ └─────────┘ 参与 └─────────┘ │
│ ↑ │
│ 单线表示部分参与:不是每个员工都参与项目 │
│ │
└─────────────────────────────────────────────────────────────────┘
2.3 E-R图的绘制方法
掌握E-R图的绘制方法是数据库设计的基本功。本节介绍E-R图的符号规范、绘制步骤和常用工具。
E-R图的基本符号
E-R图标准符号一览:
┌─────────────────────────────────────────────────────────────────┐
│ E-R图基本符号 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ │
│ │ │ 矩形:实体(Entity) │
│ │ 实体 │ 示例:学生、课程、部门 │
│ │ │ │
│ └─────────┘ │
│ │
│ ╔═════════╗ │
│ ║ ║ 双线矩形:弱实体(Weak Entity) │
│ ║ 弱实体 ║ 示例:订单明细、家属 │
│ ║ ║ │
│ ╚═════════╝ │
│ │
│ ┌───────────┐ │
│ ( 属性 ) 椭圆:属性(Attribute) │
│ └───────────┘ 示例:姓名、年龄、学号 │
│ │
│ ┌───────────┐ │
│ ( _关键属性_) 带下划线椭圆:关键属性(主键) │
│ └───────────┘ 示例:学号、身份证号 │
│ │
│ ╔═══════════╗ │
│ ║ 多值属性 ║ 双线椭圆:多值属性 │
│ ╚═══════════╝ 示例:电话号码、技能 │
│ │
│ ┌ ─ ─ ─ ─ ─┐ │
│ │ 派生属性 │ 虚线椭圆:派生属性 │
│ └ ─ ─ ─ ─ ─┘ 示例:年龄(从出生日期计算) │
│ │
│ ◇ │
│ ╱ ╲ 菱形:联系(Relationship) │
│ ╱ ╲ 示例:选修、属于、管理 │
│ ◇ ◇ │
│ │
│ ◈ │
│ ╱ ╲ 双线菱形:弱实体的标识联系 │
│ ╱ ╲ 示例:订单"包含"订单明细 │
│ ◈ ◈ │
│ │
│ ───────── 单线:部分参与(可选) │
│ ═════════ 双线:全部参与(强制) │
│ │
└─────────────────────────────────────────────────────────────────┘
符号汇总表:
| 符号 | 名称 | 含义 | 示例 |
|---|---|---|---|
| □ 矩形 | 实体 | 现实世界的事物 | 学生、课程 |
| ▢ 双线矩形 | 弱实体 | 依赖其他实体存在 | 订单明细 |
| ○ 椭圆 | 属性 | 实体的特征 | 姓名、年龄 |
| ○̲ 下划线椭圆 | 关键属性 | 唯一标识实体 | 学号 |
| ◎ 双线椭圆 | 多值属性 | 可有多个值 | 电话号码 |
| ○̇ 虚线椭圆 | 派生属性 | 计算得出 | 年龄 |
| ◇ 菱形 | 联系 | 实体间的关系 | 选修 |
| ◈ 双线菱形 | 标识联系 | 弱实体的联系 | 包含 |
| ─ 单线 | 部分参与 | 可选参与 | |
| ═ 双线 | 全部参与 | 必须参与 |
E-R图的绘制步骤
E-R图绘制流程:
┌─────────────────────────────────────────────────────────────────┐
│ E-R图绘制步骤 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 第一步:需求分析 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 理解业务场景和需求 │ │
│ │ • 收集用户描述的信息 │ │
│ │ • 明确系统边界和范围 │ │
│ │ • 输出:需求文档 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 第二步:识别实体 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 从需求描述中找出名词 │ │
│ │ • 判断哪些名词是需要管理的"事物" │ │
│ │ • 确定实体名称(使用单数形式) │ │
│ │ • 区分强实体和弱实体 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 第三步:确定属性 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 为每个实体确定描述性特征 │ │
│ │ • 识别关键属性(主键) │ │
│ │ • 区分属性类型(简单/复合、单值/多值等) │ │
│ │ • 确定属性的数据类型和约束 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 第四步:识别联系 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 从需求描述中找出动词(表示关系) │ │
│ │ • 确定联系涉及的实体 │ │
│ │ • 确定联系的基数(1:1, 1:N, M:N) │ │
│ │ • 确定联系是否有属性 │ │
│ │ • 确定参与约束(全部/部分参与) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 第五步:绘制E-R图 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 使用标准符号绘制 │ │
│ │ • 布局清晰,避免线条交叉 │ │
│ │ • 标注基数和参与约束 │ │
│ │ • 添加必要的说明和注释 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 第六步:审核与优化 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 与用户确认E-R图的正确性 │ │
│ │ • 检查是否有遗漏的实体或联系 │ │
│ │ • 检查设计是否满足业务需求 │ │
│ │ • 优化冗余和复杂度 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
实体识别技巧:
从需求描述中识别实体:
需求描述:
"学生可以选修多门课程,每门课程由一位教师讲授。
学生选课后会获得成绩。每个学生属于一个班级。"
识别过程:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 名词提取: │
│ "学生可以选修多门课程,每门课程由一位教师讲授。 │
│ 学生选课后会获得成绩。每个学生属于一个班级。" │
│ ↓ │
│ 名词:学生、课程、教师、成绩、班级 │
│ │
│ 判断是否为实体: │
│ ┌────────┬──────────────────────────┬────────────┐ │
│ │ 名词 │ 判断 │ 结论 │ │
│ ├────────┼──────────────────────────┼────────────┤ │
│ │ 学生 │ 需要管理,有多个属性 │ ✓ 实体 │ │
│ │ 课程 │ 需要管理,有多个属性 │ ✓ 实体 │ │
│ │ 教师 │ 需要管理,有多个属性 │ ✓ 实体 │ │
│ │ 成绩 │ 是"选修"联系的属性 │ ✗ 联系属性│ │
│ │ 班级 │ 需要管理,有多个属性 │ ✓ 实体 │ │
│ └────────┴──────────────────────────┴────────────┘ │
│ │
│ 动词提取(识别联系): │
│ "选修" → 学生 与 课程 之间的联系 │
│ "讲授" → 教师 与 课程 之间的联系 │
│ "属于" → 学生 与 班级 之间的联系 │
│ │
└─────────────────────────────────────────────────────────────────┘
E-R图的绘制规范
E-R图绘制规范:
┌─────────────────────────────────────────────────────────────────┐
│ 绘制规范 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 命名规范 │
│ ├── 实体名:使用单数名词(学生,而非学生们) │
│ ├── 联系名:使用动词或动词短语(选修、属于) │
│ ├── 属性名:使用名词(姓名、年龄) │
│ └── 使用业务术语,而非技术术语 │
│ │
│ 2. 布局规范 │
│ ├── 实体均匀分布,避免拥挤 │
│ ├── 联系线尽量不交叉 │
│ ├── 重要实体放在中心位置 │
│ └── 相关实体靠近放置 │
│ │
│ 3. 标注规范 │
│ ├── 必须标注基数(1:1, 1:N, M:N) │
│ ├── 标注参与约束(全部/部分) │
│ ├── 主键属性要有下划线 │
│ └── 复杂部分添加注释说明 │
│ │
│ 4. 大小规范 │
│ ├── 单张图不要过于复杂(建议不超过15个实体) │
│ ├── 复杂系统可分解为多个子图 │
│ └── 保持图形大小一致 │
│ │
└─────────────────────────────────────────────────────────────────┘
好的E-R图 vs 差的E-R图:
| 特点 | 好的E-R图 | 差的E-R图 |
|---|---|---|
| 命名 | 清晰、一致、使用业务术语 | 模糊、不一致、使用技术术语 |
| 布局 | 整齐、线条不交叉 | 混乱、线条交叉多 |
| 标注 | 完整标注基数和约束 | 缺少关键标注 |
| 复杂度 | 适度,易于理解 | 过于复杂或过于简单 |
| 完整性 | 覆盖所有业务需求 | 遗漏重要实体或联系 |
常用绘图工具介绍
E-R图绘图工具对比:
┌─────────────────────────────────────────────────────────────────┐
│ 常用绘图工具 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 专业数据库建模工具 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • PowerDesigner(Sybase) │ │
│ │ - 功能最强大的数据建模工具 │ │
│ │ - 支持正向/逆向工程 │ │
│ │ - 企业级,付费 │ │
│ │ │ │
│ │ • ERwin Data Modeler │ │
│ │ - 专业的E-R建模工具 │ │
│ │ - 支持多种数据库 │ │
│ │ - 企业级,付费 │ │
│ │ │ │
│ │ • MySQL Workbench(免费) │ │
│ │ - MySQL官方工具 │ │
│ │ - 支持E-R图设计和正向工程 │ │
│ │ - 适合MySQL项目 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 通用绘图工具 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • draw.io / diagrams.net(免费) │ │
│ │ - 在线/桌面版均可 │ │
│ │ - 内置E-R图模板 │ │
│ │ - 轻量级,易于使用 │ │
│ │ │ │
│ │ • Visio(Microsoft) │ │
│ │ - 专业的绘图工具 │ │
│ │ - 丰富的模板 │ │
│ │ - 付费 │ │
│ │ │ │
│ │ • Lucidchart(在线) │ │
│ │ - 在线协作绘图 │ │
│ │ - 支持实时协作 │ │
│ │ - 基础版免费 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 代码生成工具 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • dbdiagram.io(在线) │ │
│ │ - 用代码描述表结构 │ │
│ │ - 自动生成E-R图 │ │
│ │ - 免费版功能够用 │ │
│ │ │ │
│ │ • PlantUML │ │
│ │ - 用文本描述生成图 │ │
│ │ - 可集成到IDE │ │
│ │ - 开源免费 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
工具选择建议:
| 场景 | 推荐工具 | 理由 |
|---|---|---|
| 学习/小项目 | draw.io, dbdiagram.io | 免费、简单、够用 |
| 中型项目 | MySQL Workbench | 免费、可生成SQL |
| 企业级项目 | PowerDesigner, ERwin | 功能强大、正逆向工程 |
| 团队协作 | Lucidchart | 实时协作、云端保存 |
| 文档集成 | PlantUML | 可嵌入代码/Markdown |
2.4 扩展E-R模型(EER)
传统的E-R模型虽然简洁,但在表达复杂业务场景时存在局限。**扩展E-R模型(Enhanced Entity-Relationship Model,EER)**引入了更多语义概念,能够更准确地描述现实世界。
泛化与特化(Generalization/Specialization)
**泛化(Generalization)和特化(Specialization)**是描述实体之间继承关系的概念,类似于面向对象编程中的继承。
泛化与特化的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 泛化与特化 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 特化(Specialization):自顶向下 │
│ 将一个实体类型分解为多个子类型 │
│ │
│ ┌─────────┐ │
│ │ 员工 │ ← 父实体(超类) │
│ └────┬────┘ │
│ │ │
│ ┌─────┼─────┐ │
│ │ │ │ │
│ ┌────┴───┐ │ ┌───┴────┐ │
│ │ 全职员工│ │ │兼职员工│ ← 子实体(子类) │
│ └────────┘ │ └────────┘ │
│ │ │
│ ┌─────┴─────┐ │
│ │ 实习生 │ │
│ └───────────┘ │
│ │
│ 泛化(Generalization):自底向上 │
│ 将多个具有共同特征的实体类型合并为一个父类型 │
│ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ 汽车 │ │ 卡车 │ │ 摩托车 │ ← 子实体 │
│ └───┬────┘ └───┬────┘ └───┬────┘ │
│ │ │ │ │
│ └───────────┼───────────┘ │
│ │ │
│ ┌────┴────┐ │
│ │ 车辆 │ ← 父实体(泛化而来) │
│ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
特化的约束类型:
特化约束:
┌─────────────────────────────────────────────────────────────────┐
│ │
│ 1. 不相交约束(Disjoint) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一个实体只能属于一个子类 │ │
│ │ │ │
│ │ ┌─────────┐ │ │
│ │ │ 员工 │ │ │
│ │ └────┬────┘ │ │
│ │ ◯ d ← d = disjoint(不相交) │ │
│ │ ┌───┴───┐ │ │
│ │ ┌────┴───┐ ┌─┴────┐ │ │
│ │ │ 男员工│ │女员工│ ← 一个员工只能是男或女 │ │
│ │ └────────┘ └──────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 重叠约束(Overlapping) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一个实体可以属于多个子类 │ │
│ │ │ │
│ │ ┌─────────┐ │ │
│ │ │ 员工 │ │ │
│ │ └────┬────┘ │ │
│ │ ◯ o ← o = overlapping(重叠) │ │
│ │ ┌───┴───┐ │ │
│ │ ┌────┴───┐ ┌─┴────┐ │ │
│ │ │ 技术员 │ │ 经理 │ ← 一个员工可以既是技术员又是经理│ │
│ │ └────────┘ └──────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 完全特化(Total) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 父类中每个实体都必须属于某个子类 │ │
│ │ 图形表示:双线连接 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4. 部分特化(Partial) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 父类中的实体可以不属于任何子类 │ │
│ │ 图形表示:单线连接 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
泛化/特化的实例:
| 场景 | 父实体 | 子实体 | 约束 |
|---|---|---|---|
| 人员管理 | 人员 | 学生、教师 | 不相交、完全 |
| 账户系统 | 账户 | 储蓄账户、支票账户 | 不相交、部分 |
| 车辆管理 | 车辆 | 轿车、卡车、摩托车 | 不相交、完全 |
| 员工角色 | 员工 | 工程师、经理、销售 | 重叠、部分 |
聚合(Aggregation)
**聚合(Aggregation)**用于表示"整体-部分"关系,或将一个联系视为一个高级实体参与另一个联系。
聚合的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 聚合 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 场景:员工在某个项目中使用某种设备 │
│ │
│ 问题:三元联系过于复杂 │
│ │
│ 解决方案:使用聚合 │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌────────┐ ◇ ┌────────┐ │ │
│ │ │ 员工 │─────── 参与 ───────│ 项目 │ │ │
│ │ └────────┘ ◇ └────────┘ │ │
│ │ │ │ │
│ └──────────────────────┼──────────────────────────────────┘ │
│ │ │
│ 聚合(将"员工参与项目"作为一个整体) │
│ │ │
│ ◇ 使用 │
│ │ │
│ ┌────┴────┐ │
│ │ 设备 │ │
│ └─────────┘ │
│ │
│ 含义:在"员工参与项目"的基础上,使用设备 │
│ 这比简单的三元联系更能表达语义 │
│ │
└─────────────────────────────────────────────────────────────────┘
聚合的图形表示:
聚合的符号表示(用虚线矩形包围):
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
│ │
┌────────┐ ◇ ┌────────┐
│ │ 员工 │───── 参与 ─────│ 项目 │ │
└────────┘ ◇ └────────┘
│ │
└ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
│
◇ 使用
│
┌────┴────┐
│ 设备 │
└─────────┘
关联实体(Associative Entity)
关联实体(Associative Entity) ,也称为交叉实体,是将M:N联系转换为一个独立实体的方式。
关联实体的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 关联实体 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 场景:学生选课,需要记录成绩 │
│ │
│ 传统M:N联系: │
│ │
│ ┌────────┐ M N ┌────────┐ │
│ │ 学生 │──────── 选修 ────────│ 课程 │ │
│ └────────┘ │ └────────┘ │
│ │ │
│ ┌──┴──┐ │
│ │成绩 │ │
│ └─────┘ │
│ │
│ 转换为关联实体: │
│ │
│ ┌────────┐ 1 N ┌────────────┐ │
│ │ 学生 │───────────────────────│ 选课 │ │
│ └────────┘ │ (关联实体) │ │
│ │ ─────────── │ │
│ │ 成绩 │ │
│ ┌────────┐ 1 N │ 选课日期 │ │
│ │ 课程 │───────────────────────└────────────┘ │
│ └────────┘ │
│ │
│ 关联实体"选课": │
│ • 有自己的属性(成绩、选课日期) │
│ • 将M:N联系转换为两个1:N联系 │
│ • 更容易转换为关系模型 │
│ │
└─────────────────────────────────────────────────────────────────┘
关联实体的特点:
| 特点 | 说明 |
|---|---|
| 来源 | 从M:N联系演变而来 |
| 主键 | 通常由两个外键组成(复合主键) |
| 属性 | 可以有自己的属性 |
| 作用 | 简化M:N联系,便于转换为表 |
| 示例 | 选课、订单明细、医生就诊记录 |
EER与传统E-R模型的对比
EER vs 传统E-R模型对比:
┌─────────────────────────────────────────────────────────────────┐
│ E-R模型 vs EER模型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 传统E-R模型 EER模型 │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ │ │ │ │
│ │ 基本概念: │ │ 基本概念: │ │
│ │ • 实体 │ │ • 实体 │ │
│ │ • 属性 │ │ • 属性 │ │
│ │ • 联系 │ │ • 联系 │ │
│ │ │ │ │ │
│ │ │ │ 扩展概念: │ │
│ │ │ │ • 泛化/特化(继承) │ │
│ │ │ │ • 聚合(整体-部分) │ │
│ │ │ │ • 关联实体 │ │
│ │ │ │ • 分类/类别 │ │
│ │ │ │ │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
│ │
│ 适用场景 适用场景 │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ • 简单业务场景 │ │ • 复杂业务场景 │ │
│ │ • 快速原型设计 │ │ • 需要表达继承关系 │ │
│ │ • 教学和学习 │ │ • 企业级应用设计 │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
对比总结表:
| 对比维度 | 传统E-R模型 | EER模型 |
|---|---|---|
| 表达能力 | 基本 | 强大 |
| 学习难度 | 简单 | 较复杂 |
| 继承关系 | 不支持 | 支持(泛化/特化) |
| 整体-部分 | 不支持 | 支持(聚合) |
| 适用规模 | 小型系统 | 中大型系统 |
| 与OO的契合 | 较低 | 较高 |
2.5 E-R模型到关系模型的转换
E-R模型是概念层的设计,最终需要转换为关系模型才能在数据库中实现。本节介绍转换的规则和方法。
转换的基本思路
E-R模型到关系模型的转换流程:
┌─────────────────────────────────────────────────────────────────┐
│ 转换基本思路 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ E-R模型 关系模型 │
│ ┌─────────────────────────┐ ┌─────────────────────────┐ │
│ │ │ │ │ │
│ │ 实体 ─────────────────────→ 表(Table) │ │
│ │ │ │ │ │
│ │ 属性 ─────────────────────→ 列/字段(Column) │ │
│ │ │ │ │ │
│ │ 关键属性 ───────────────────→ 主键(Primary Key) │ │
│ │ │ │ │ │
│ │ 联系 ─────────────────────→ 外键 或 独立表 │ │
│ │ │ │ │ │
│ └─────────────────────────┘ └─────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
实体转换为关系
规则:每个实体转换为一个表,属性转换为列,关键属性转换为主键。
实体转换示例:
E-R模型中的实体:
┌───────────────────────────────────────────────────┐
│ │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │_学号_│ │ 姓名 │ │ 年龄 │ │
│ └───┬──┘ └───┬──┘ └───┬──┘ │
│ │ │ │ │
│ └────┬────┴────┬────┘ │
│ │ │ │
│ ┌────┴─────────┴────┐ │
│ │ 学生 │ │
│ └───────────────────┘ │
│ │
└───────────────────────────────────────────────────┘
转换后的关系表:
students(学生表)
┌──────────┬──────────┬──────────┐
│ id(PK) │ name │ age │
├──────────┼──────────┼──────────┤
│ 001 │ 张三 │ 20 │
│ 002 │ 李四 │ 21 │
│ 003 │ 王五 │ 19 │
└──────────┴──────────┴──────────┘
SQL语句:
CREATE TABLE students (
id VARCHAR(10) PRIMARY KEY,
name VARCHAR(50) NOT NULL,
age INT
);
属性转换
不同类型的属性有不同的转换规则:
属性转换规则:
┌─────────────────────────────────────────────────────────────────┐
│ 属性转换规则 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 简单属性 → 直接转换为一个列 │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 属性:姓名 → 列:name VARCHAR(50) │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ 2. 复合属性 → 展开为多个列,或存储为JSON │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 属性:地址(省、市、街道) │ │
│ │ → province VARCHAR(20), │ │
│ │ city VARCHAR(30), │ │
│ │ street VARCHAR(100) │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ 3. 多值属性 → 创建独立的表 │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 属性:电话号码(多个) │ │
│ │ → CREATE TABLE student_phones ( │ │
│ │ student_id VARCHAR(10), │ │
│ │ phone VARCHAR(20), │ │
│ │ PRIMARY KEY (student_id, phone), │ │
│ │ FOREIGN KEY (student_id) REFERENCES students │ │
│ │ ); │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ 4. 派生属性 → 通常不存储,用视图或计算列表示 │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 属性:年龄(从出生日期派生) │ │
│ │ → 存储birth_date,需要时计算年龄 │ │
│ │ → 或使用计算列: │ │
│ │ age AS DATEDIFF(YEAR, birth_date, GETDATE()) │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
联系转换
联系的转换规则取决于联系的类型(1:1, 1:N, M:N):
一对一联系(1:1)的转换
1:1联系的转换方法:
场景:员工 ─1:1─ 工位
┌─────────────────────────────────────────────────────────────────┐
│ 1:1联系转换 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 方法1:合并到任一方(推荐) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ employees │ │
│ │ ┌───────────┬──────────┬───────────────┐ │ │
│ │ │ id(PK) │ name │ workstation_id│ │ │
│ │ └───────────┴──────────┴───────────────┘ │ │
│ │ ↓ │ │
│ │ 外键 │ │
│ │ ↓ │ │
│ │ workstations │ │
│ │ ┌───────────┬──────────┐ │ │
│ │ │ id(PK) │ location │ │ │
│ │ └───────────┴──────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 方法2:创建独立联系表(联系有属性时使用) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ emp_workstation │ │
│ │ ┌─────────────┬────────────────┬────────────┐ │ │
│ │ │employee_id │ workstation_id │assign_date │ │ │
│ │ │(PK,FK) │ (UNIQUE,FK) │ │ │ │
│ │ └─────────────┴────────────────┴────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
SQL示例(方法1):
CREATE TABLE workstations (
id INT PRIMARY KEY,
location VARCHAR(100)
);
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(50),
workstation_id INT UNIQUE, -- UNIQUE保证1:1
FOREIGN KEY (workstation_id) REFERENCES workstations(id)
);
一对多联系(1:N)的转换
1:N联系的转换方法:
场景:部门 ─1:N─ 员工(一个部门有多个员工)
┌─────────────────────────────────────────────────────────────────┐
│ 1:N联系转换 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 方法:在"N"方添加外键(指向"1"方) │
│ │
│ departments(1方) │
│ ┌───────────┬──────────────┐ │
│ │ id(PK) │ dept_name │ │
│ └───────────┴──────────────┘ │
│ ↑ │
│ │ 被引用 │
│ │ │
│ employees(N方) │
│ ┌───────────┬──────────┬─────────────┐ │
│ │ id(PK) │ name │ dept_id(FK) │ ← 外键放在N方 │
│ └───────────┴──────────┴─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
SQL示例:
CREATE TABLE departments (
id INT PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL
);
CREATE TABLE employees (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES departments(id)
);
多对多联系(M:N)的转换
M:N联系的转换方法:
场景:学生 ─M:N─ 课程(学生选课,带成绩属性)
┌─────────────────────────────────────────────────────────────────┐
│ M:N联系转换 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 方法:创建独立的联系表(关联表/中间表) │
│ │
│ students enrollments courses │
│ ┌─────────┬──────┐ ┌──────────────────┐ ┌─────────┬──────┐
│ │id(PK) │name │ │student_id(PK,FK) │ │id(PK) │title │
│ └────┬────┴──────┘ │course_id(PK,FK) │ └────┬────┴──────┘
│ │ │grade │ │ │
│ │ 1:N │enroll_date │ N:1 │ │
│ └───────────────────→└──────────────────┘←───────┘ │
│ │
│ M:N联系被分解为两个1:N联系 │
│ │
└─────────────────────────────────────────────────────────────────┘
SQL示例:
CREATE TABLE students (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL
);
CREATE TABLE courses (
id INT PRIMARY KEY,
title VARCHAR(100) NOT NULL
);
-- 联系表(关联表)
CREATE TABLE enrollments (
student_id INT,
course_id INT,
grade DECIMAL(4,1),
enroll_date DATE,
PRIMARY KEY (student_id, course_id), -- 复合主键
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
联系转换规则汇总
| 联系类型 | 转换方法 | 外键位置 | 示例 |
|---|---|---|---|
| 1:1 | 合并或独立表 | 任一方(加UNIQUE) | 员工-工位 |
| 1:N | N方加外键 | N方 | 部门-员工 |
| M:N | 创建联系表 | 联系表中两个外键 | 学生-课程 |
转换实例演示
完整转换案例:图书馆管理系统
图书馆E-R模型:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 读者 │───M:N────│ 借阅 │───M:N────│ 图书 │
│ │ │(借阅日期)│ │ │
└────┬────┘ └─────────┘ └────┬────┘
│ │
│ 1:N │ N:1
│ │
┌────┴────┐ ┌────┴────┐
│借阅记录 │ │ 类别 │
└─────────┘ └─────────┘
转换为关系模型:
sql
-- 1. 实体转换
CREATE TABLE readers (
reader_id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
phone VARCHAR(20),
email VARCHAR(100)
);
CREATE TABLE categories (
category_id INT PRIMARY KEY,
category_name VARCHAR(50) NOT NULL
);
CREATE TABLE books (
book_id INT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
author VARCHAR(100),
isbn VARCHAR(20) UNIQUE,
category_id INT, -- 1:N联系,外键放在N方
FOREIGN KEY (category_id) REFERENCES categories(category_id)
);
-- 2. M:N联系转换为联系表
CREATE TABLE borrowings (
borrow_id INT PRIMARY KEY AUTO_INCREMENT,
reader_id INT NOT NULL,
book_id INT NOT NULL,
borrow_date DATE NOT NULL,
due_date DATE NOT NULL,
return_date DATE,
FOREIGN KEY (reader_id) REFERENCES readers(reader_id),
FOREIGN KEY (book_id) REFERENCES books(book_id)
);
-- 创建索引优化查询
CREATE INDEX idx_borrowings_reader ON borrowings(reader_id);
CREATE INDEX idx_borrowings_book ON borrowings(book_id);
转换结果的ER图(关系模型):
关系模型表结构:
readers books categories
┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐
│ reader_id (PK) │ │ book_id (PK) │ │category_id(PK)│
│ name │ │ title │ │category_name │
│ phone │ │ author │ └──────────────┘
│ email │ │ isbn │ ↑
└────────┬────────┘ │ category_id(FK)─┼──────────────┘
│ └────────┬────────┘
│ │
│ 1:N N:1 │
↓ ↓
┌────────────────────────────────────────┐
│ borrowings │
├────────────────────────────────────────┤
│ borrow_id (PK) │
│ reader_id (FK) ────────────────────────┤
│ book_id (FK) ──────────────────────────┤
│ borrow_date │
│ due_date │
│ return_date │
└────────────────────────────────────────┘
2.6 E-R模型设计实例
本节通过一个完整的在线商城系统案例,演示E-R模型设计的全过程。
需求分析
在线商城系统需求描述:
┌─────────────────────────────────────────────────────────────────┐
│ 在线商城系统需求 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 业务描述: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. 用户可以注册账号并登录系统 │ │
│ │ 2. 用户可以浏览商品,商品属于不同的类别 │ │
│ │ 3. 用户可以将商品添加到购物车 │ │
│ │ 4. 用户可以下单购买商品,一个订单可以包含多个商品 │ │
│ │ 5. 每个订单需要记录收货地址 │ │
│ │ 6. 用户可以对已购买的商品进行评价 │ │
│ │ 7. 系统需要记录商品的库存信息 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 功能模块: │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │用户管理│ │商品管理│ │购物车 │ │订单管理│ │评价管理│ │
│ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
实体识别
从需求描述中识别实体:
实体识别过程:
需求描述中的名词分析:
┌──────────────┬────────────────────────────┬────────────┐
│ 名词 │ 分析 │ 结论 │
├──────────────┼────────────────────────────┼────────────┤
│ 用户 │ 核心对象,需要管理 │ ✓ 实体 │
│ 账号 │ 用户的一部分 │ ✗ 属性 │
│ 商品 │ 核心对象,需要管理 │ ✓ 实体 │
│ 类别 │ 独立分类,需要单独管理 │ ✓ 实体 │
│ 购物车 │ 用户与商品的临时联系 │ ✓ 实体 │
│ 订单 │ 核心对象,需要管理 │ ✓ 实体 │
│ 收货地址 │ 用户的附属信息 │ ✓ 实体 │
│ 评价 │ 用户对商品的评价记录 │ ✓ 实体 │
│ 库存 │ 商品的属性 │ ✗ 属性 │
└──────────────┴────────────────────────────┴────────────┘
识别出的实体:
┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐
│用户 │ │商品 │ │类别 │ │购物车│ │订单 │ │地址 │ │评价 │
└─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘
属性确定
为每个实体确定属性:
实体属性设计:
┌─────────────────────────────────────────────────────────────────┐
│ 实体属性 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 用户(User) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • user_id (PK) 用户ID │ │
│ │ • username 用户名(唯一) │ │
│ │ • password 密码(加密存储) │ │
│ │ • email 邮箱 │ │
│ │ • phone 手机号 │ │
│ │ • created_at 注册时间 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 商品(Product) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • product_id (PK) 商品ID │ │
│ │ • name 商品名称 │ │
│ │ • description 商品描述 │ │
│ │ • price 价格 │ │
│ │ • stock 库存数量 │ │
│ │ • image_url 商品图片 │ │
│ │ • created_at 上架时间 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 类别(Category) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • category_id (PK) 类别ID │ │
│ │ • name 类别名称 │ │
│ │ • parent_id 父类别ID(支持多级分类) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 地址(Address) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • address_id (PK) 地址ID │ │
│ │ • province 省 │ │
│ │ • city 市 │ │
│ │ • district 区 │ │
│ │ • detail 详细地址 │ │
│ │ • receiver 收件人姓名 │ │
│ │ • phone 收件人电话 │ │
│ │ • is_default 是否默认地址 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 订单(Order) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • order_id (PK) 订单ID │ │
│ │ • order_no 订单编号(唯一) │ │
│ │ • total_amount 订单总金额 │ │
│ │ • status 订单状态 │ │
│ │ • created_at 下单时间 │ │
│ │ • paid_at 支付时间 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 订单明细(OrderItem)- 弱实体 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • item_id (PK) 明细ID │ │
│ │ • quantity 购买数量 │ │
│ │ • price 成交单价 │ │
│ │ • subtotal 小计金额 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 评价(Review) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • review_id (PK) 评价ID │ │
│ │ • rating 评分(1-5星) │ │
│ │ • content 评价内容 │ │
│ │ • created_at 评价时间 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 购物车(Cart) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • cart_id (PK) 购物车ID │ │
│ │ • quantity 数量 │ │
│ │ • added_at 添加时间 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
联系建立
实体间的联系分析:
┌─────────────────────────────────────────────────────────────────┐
│ 联系分析 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 用户 与 地址:一对多(1:N) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一个用户可以有多个收货地址 │ │
│ │ 一个地址只属于一个用户 │ │
│ │ 用户 ──1:N──→ 地址 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 类别 与 商品:一对多(1:N) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一个类别下有多个商品 │ │
│ │ 一个商品属于一个类别 │ │
│ │ 类别 ──1:N──→ 商品 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 用户 与 订单:一对多(1:N) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一个用户可以下多个订单 │ │
│ │ 一个订单属于一个用户 │ │
│ │ 用户 ──1:N──→ 订单 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4. 订单 与 订单明细:一对多(1:N)- 弱实体联系 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一个订单包含多个订单明细 │ │
│ │ 订单明细依赖于订单存在 │ │
│ │ 订单 ══1:N══→ 订单明细 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 5. 商品 与 订单明细:一对多(1:N) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 一个商品可以出现在多个订单明细中 │ │
│ │ 一个订单明细对应一个商品 │ │
│ │ 商品 ──1:N──→ 订单明细 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 6. 用户 与 商品 与 购物车:多对多(通过购物车关联) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 用户 ──1:N──→ 购物车 ←──N:1── 商品 │ │
│ │ 购物车是关联实体 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 7. 用户 与 商品 与 评价:多对多(通过评价关联) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 用户 ──1:N──→ 评价 ←──N:1── 商品 │ │
│ │ 评价是关联实体 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 8. 订单 与 地址:多对一(N:1) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 多个订单可以使用同一个地址 │ │
│ │ 一个订单对应一个收货地址 │ │
│ │ 订单 ──N:1──→ 地址 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
完整E-R图绘制
在线商城系统完整E-R图:
┌──────────┐
│ 类别 │
│Category │
└────┬─────┘
│
1:N│
↓
┌──────────┐ 1:N ┌──────────┐ N:1 ┌──────────┐
│ 用户 │───────────→│ 购物车 │←───────────│ 商品 │
│ User │ │ Cart │ │ Product │
└────┬─────┘ └──────────┘ └────┬─────┘
│ │
│ 1:N 1:N │
↓ ↓
┌──────────┐ ┌──────────┐
│ 地址 │ │ 评价 │
│ Address │ │ Review │
└────┬─────┘ └────┬─────┘
│ │
N:1│ N:1│
↓ ↓
┌──────────┐ 1:N ╔══════════╗ N:1 ┌──────────┐
│ 订单 │═══════════→║订单明细 ║←───────────│ 商品 │
│ Order │ ║OrderItem ║ │ Product │
└────┬─────┘ ╚══════════╝ └──────────┘
│
N:1│
↓
┌──────────┐
│ 用户 │
│ User │
└──────────┘
转换为关系模型(SQL):
sql
-- 用户表
CREATE TABLE users (
user_id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
email VARCHAR(100),
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 类别表(支持多级分类)
CREATE TABLE categories (
category_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
parent_id INT,
FOREIGN KEY (parent_id) REFERENCES categories(category_id)
);
-- 商品表
CREATE TABLE products (
product_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(200) NOT NULL,
description TEXT,
price DECIMAL(10, 2) NOT NULL,
stock INT DEFAULT 0,
image_url VARCHAR(500),
category_id INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (category_id) REFERENCES categories(category_id)
);
-- 地址表
CREATE TABLE addresses (
address_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
province VARCHAR(50),
city VARCHAR(50),
district VARCHAR(50),
detail VARCHAR(200),
receiver VARCHAR(50),
phone VARCHAR(20),
is_default BOOLEAN DEFAULT FALSE,
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
-- 订单表
CREATE TABLE orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
order_no VARCHAR(50) NOT NULL UNIQUE,
user_id INT NOT NULL,
address_id INT,
total_amount DECIMAL(10, 2) NOT NULL,
status ENUM('pending', 'paid', 'shipped', 'completed', 'cancelled') DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
paid_at TIMESTAMP NULL,
FOREIGN KEY (user_id) REFERENCES users(user_id),
FOREIGN KEY (address_id) REFERENCES addresses(address_id)
);
-- 订单明细表(弱实体)
CREATE TABLE order_items (
item_id INT PRIMARY KEY AUTO_INCREMENT,
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
price DECIMAL(10, 2) NOT NULL,
subtotal DECIMAL(10, 2) NOT NULL,
FOREIGN KEY (order_id) REFERENCES orders(order_id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
-- 购物车表(关联实体)
CREATE TABLE carts (
cart_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL DEFAULT 1,
added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE KEY (user_id, product_id),
FOREIGN KEY (user_id) REFERENCES users(user_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
-- 评价表(关联实体)
CREATE TABLE reviews (
review_id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
product_id INT NOT NULL,
rating TINYINT CHECK (rating >= 1 AND rating <= 5),
content TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(user_id),
FOREIGN KEY (product_id) REFERENCES products(product_id)
);
-- 创建索引优化查询
CREATE INDEX idx_products_category ON products(category_id);
CREATE INDEX idx_orders_user ON orders(user_id);
CREATE INDEX idx_order_items_order ON order_items(order_id);
CREATE INDEX idx_reviews_product ON reviews(product_id);
设计总结:
| 设计要素 | 数量 | 说明 |
|---|---|---|
| 实体 | 8个 | 用户、商品、类别、地址、订单、订单明细、购物车、评价 |
| 弱实体 | 1个 | 订单明细(依赖订单) |
| 关联实体 | 2个 | 购物车、评价(处理M:N关系) |
| 1:N联系 | 5个 | 用户-地址、类别-商品、用户-订单等 |
| 自引用联系 | 1个 | 类别的多级分类 |
第三章 层次模型
层次模型是最早出现的数据库数据模型之一,曾在数据库发展史上占据重要地位。虽然现在已经被关系模型取代,但理解层次模型有助于我们更好地理解数据库技术的演进。
3.1 层次模型概述
层次模型的定义
层次模型(Hierarchical Model)是用树形结构来表示实体及其联系的数据模型。在层次模型中,数据被组织成一棵倒置的树,节点代表记录类型,边代表父子关系。
层次模型的基本概念:
┌─────────────────────────────────────────────────────────────────┐
│ 层次模型结构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ │
│ │ 根节点 │ ← 树的顶端,只有一个 │
│ │(公司) │ │
│ └────┬────┘ │
│ │ │
│ ┌──────────────┼──────────────┐ │
│ ↓ ↓ ↓ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ 部门A │ │ 部门B │ │ 部门C │ ← 子节点 │
│ └───┬────┘ └───┬────┘ └───┬────┘ │
│ │ │ │ │
│ ┌────┼────┐ ┌────┼────┐ ┌────┼────┐ │
│ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ │
│ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ │
│ │员│ │员│ │员│ │员│ │员│ │员│ │员│ │员│ │员│ ← 叶节点 │
│ │工│ │工│ │工│ │工│ │工│ │工│ │工│ │工│ │工│ │
│ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ │
│ │
│ 特点: │
│ • 有且只有一个根节点 │
│ • 每个节点(除根节点外)有且只有一个父节点 │
│ • 从根到任意节点只有一条路径 │
│ │
└─────────────────────────────────────────────────────────────────┘
层次模型的起源
IMS(Information Management System)是最著名的层次数据库系统,由IBM公司 于1968年开发。
层次模型的历史背景:
┌─────────────────────────────────────────────────────────────────┐
│ 发展历程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1966年 ───────────────────────────────────────────────────── │
│ │ 背景:NASA阿波罗登月计划需要管理大量零部件信息 │
│ │ 挑战:物料清单(BOM)天然具有层次结构 │
│ │ │
│ │ 火箭 │
│ │ ├── 第一级推进器 │
│ │ │ ├── 燃料箱 │
│ │ │ └── 发动机 │
│ │ ├── 第二级推进器 │
│ │ └── 指令舱 │
│ ↓ │
│ 1968年 ───────────────────────────────────────────────────── │
│ │ IBM与北美航空公司联合开发IMS │
│ │ 最初用于管理阿波罗计划的物料清单 │
│ ↓ │
│ 1970s ────────────────────────────────────────────────────── │
│ │ IMS成为最成功的层次数据库 │
│ │ 广泛应用于银行、保险、制造业 │
│ ↓ │
│ 现在 ─────────────────────────────────────────────────────── │
│ IMS仍在一些大型企业的核心系统中运行 │
│ 处理着关键业务数据 │
│ │
└─────────────────────────────────────────────────────────────────┘
层次模型发展里程碑:
| 年份 | 事件 | 意义 |
|---|---|---|
| 1966 | 阿波罗计划启动 | 产生大规模数据管理需求 |
| 1968 | IBM发布IMS | 第一个商用层次数据库 |
| 1969 | 阿波罗11号登月 | IMS在实际任务中验证 |
| 1970s | IMS广泛商用 | 成为企业级数据库标准 |
| 1970 | E.F.Codd提出关系模型 | 层次模型开始被挑战 |
| 1980s | 关系数据库崛起 | 层次数据库市场萎缩 |
层次模型的基本特点
层次模型的核心特点:
┌─────────────────────────────────────────────────────────────────┐
│ 基本特点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 树形结构 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 数据组织成倒置的树形 │ │
│ │ • 从根到叶形成层次 │ │
│ │ • 直观反映现实中的层次关系 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 父子关系 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 一个父节点可以有多个子节点(1:N) │ │
│ │ • 一个子节点只能有一个父节点 │ │
│ │ • 不能直接表示多对多关系 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 导航式访问 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 从根节点开始,沿着路径访问数据 │ │
│ │ • 需要知道数据的存储路径 │ │
│ │ • 类似于文件系统的目录结构 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4. 记录类型 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 每个节点是一种记录类型 │ │
│ │ • 记录类型包含多个字段 │ │
│ │ • 记录类型之间有父子联系 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
层次模型适用场景:
| 场景 | 说明 | 示例 |
|---|---|---|
| 组织结构 | 天然的层次关系 | 公司→部门→员工 |
| 物料清单(BOM) | 产品由部件组成 | 汽车→发动机→零件 |
| 文件系统 | 目录和文件的关系 | 根目录→子目录→文件 |
| 行政区划 | 国家→省→市→区 | 地理数据管理 |
| 分类体系 | 类别的上下级关系 | 商品分类 |
3.2 层次模型的数据结构
层次模型使用树形结构组织数据,本节详细介绍其数据结构的各个组成部分。
树形结构特征
层次模型的树形结构:
┌─────────────────────────────────────────────────────────────────┐
│ 树形结构术语 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Level 0 │
│ ┌────────┐ │
│ │ A │ ← 根节点(Root) │
│ └───┬────┘ │
│ │ │
│ ┌────────────────┼────────────────┐ Level 1 │
│ ↓ ↓ ↓ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ B │ │ C │ │ D │ ← 内部节点 │
│ └───┬────┘ └───┬────┘ └────────┘ │
│ │ │ │
│ ┌────┴────┐ ┌────┴────┐ Level 2 │
│ ↓ ↓ ↓ ↓ │
│ ┌────────┐┌────────┐┌────────┐┌────────┐ │
│ │ E ││ F ││ G ││ H │ ← 叶节点(Leaf) │
│ └────────┘└────────┘└────────┘└────────┘ │
│ │
│ 树形结构的数学定义: │
│ • 根节点:没有父节点的节点,树中唯一 │
│ • 内部节点:有子节点的非根节点 │
│ • 叶节点:没有子节点的节点 │
│ • 层次(Level):根为第0层,子节点比父节点多1层 │
│ • 深度(Depth):树的最大层次数 │
│ │
└─────────────────────────────────────────────────────────────────┘
根节点与子节点
节点关系示意:
┌─────────────────────────────────────────────────────────────────┐
│ 节点类型与关系 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 根节点(Root Node) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 位于树的最顶端 │ │
│ │ • 没有父节点 │ │
│ │ • 每棵树有且只有一个根节点 │ │
│ │ • 是访问所有数据的入口点 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 子节点(Child Node) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 直接位于某节点下方的节点 │ │
│ │ • 一个父节点可以有0个或多个子节点 │ │
│ │ • 子节点的顺序通常有意义(有序树) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 示例:公司组织结构 │
│ │
│ ┌──────────────┐ │
│ │ 公司(根) │ │
│ │ Company │ │
│ └──────┬───────┘ │
│ │ │
│ ┌─────────┼─────────┐ │
│ ↓ ↓ ↓ │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │研发部│ │销售部│ │财务部│ ← 公司的子节点 │
│ └──────┘ └──────┘ └──────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
双亲节点与孩子节点
父子关系详解:
┌─────────────────────────────────────────────────────────────────┐
│ 双亲-孩子关系 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 双亲节点(Parent Node) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 直接连接某节点的上层节点 │ │
│ │ • 除根节点外,每个节点有且只有一个双亲节点 │ │
│ │ • 体现层次模型的"单父"特征 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 孩子节点(Child Node) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 双亲节点直接连接的下层节点 │ │
│ │ • 一个双亲可以有多个孩子(1:N关系) │ │
│ │ • 没有孩子的节点称为叶节点 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 兄弟节点(Sibling Node) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 具有相同双亲节点的节点互为兄弟 │ │
│ │ • 兄弟节点在同一层次 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 关系图示: │
│ │
│ ┌────────┐ │
│ │ A │ ← A是B、C的双亲节点 │
│ └───┬────┘ │
│ │ │
│ ┌─────┴─────┐ │
│ ↓ ↓ │
│ ┌────────┐ ┌────────┐ │
│ │ B │ │ C │ ← B和C互为兄弟节点 │
│ │ │ │ │ B和C都是A的孩子节点 │
│ └───┬────┘ └────────┘ │
│ ↓ │
│ ┌────────┐ │
│ │ D │ ← D是B的孩子,A的孙子(后代) │
│ └────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
层次模型的存储结构
层次模型的物理存储方式:
┌─────────────────────────────────────────────────────────────────┐
│ 存储结构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 邻接方法(Adjacency Method) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 按层次顺序存储,先存父节点,再存所有子节点 │ │
│ │ │ │
│ │ 存储顺序:A → B → E → F → C → G → H → D │ │
│ │ │ │
│ │ 逻辑结构: │ │
│ │ A │ │
│ │ /|\ │ │
│ │ B C D │ │
│ │ /| |\ │ │
│ │ E F G H │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 链接方法(Child-Sibling Method) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 每个节点包含: │ │
│ │ • 数据域(Data) │ │
│ │ • 第一个孩子指针(First Child Pointer) │ │
│ │ • 下一个兄弟指针(Next Sibling Pointer) │ │
│ │ │ │
│ │ 结构示意: │ │
│ │ ┌───────┬───────┬───────┐ │ │
│ │ │ Data │ Child │Sibling│ │ │
│ │ └───────┴───┬───┴───┬───┘ │ │
│ │ ↓ → │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 层次顺序存储(Hierarchical Sequence) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ IMS使用的存储方式 │ │
│ │ 按前序遍历顺序存储所有记录 │ │
│ │ 便于从根到叶的顺序访问 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
存储结构比较:
| 存储方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 邻接方法 | 结构简单 | 插入删除需移动数据 | 静态数据 |
| 链接方法 | 插入删除灵活 | 需要额外指针空间 | 动态数据 |
| 层次顺序 | 顺序访问快 | 维护成本高 | 大规模数据 |
3.3 层次模型的数据操作
层次模型的数据操作采用导航式访问方式,需要从根节点开始,沿着层次路径访问数据。
查询操作
层次模型的查询方式:
┌─────────────────────────────────────────────────────────────────┐
│ 查询操作 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 导航式查询: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. 定位根节点 │ │
│ │ 2. 沿着路径向下导航 │ │
│ │ 3. 到达目标节点获取数据 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 示例:查找"研发部的张三" │
│ │
│ ┌──────────┐ │
│ 1 │ 公司 │ ← 步骤1:定位根节点 │
│ └────┬─────┘ │
│ ↓ │
│ ┌──────────┐ │
│ 2 │ 研发部 │ ← 步骤2:导航到"研发部" │
│ └────┬─────┘ │
│ ↓ │
│ ┌──────────┐ │
│ 3 │ 张三 │ ← 步骤3:在子节点中查找"张三" │
│ └──────────┘ │
│ │
│ IMS查询语言示例(DL/I): │
│ GU COMPANY(COMP_NAME='ABC公司') │
│ DEPARTMENT(DEPT_NAME='研发部') │
│ EMPLOYEE(EMP_NAME='张三') │
│ │
└─────────────────────────────────────────────────────────────────┘
插入操作
层次模型的插入规则:
┌─────────────────────────────────────────────────────────────────┐
│ 插入操作 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 规则:子节点必须依附于父节点存在 │
│ │
│ 插入流程: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. 如果插入根节点,直接插入 │ │
│ │ 2. 如果插入子节点,必须先确保父节点存在 │ │
│ │ 3. 不能插入没有父节点的非根记录 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 示例:插入新员工"李四"到"销售部" │
│ │
│ ✓ 正确操作流程: │
│ 1. 定位到"销售部"节点(父节点) │
│ 2. 在其下插入"李四"记录 │
│ │
│ ✗ 错误操作: │
│ 直接插入员工记录而不指定部门 → 违反约束 │
│ │
│ IMS命令: │
│ GU DEPARTMENT(DEPT_NAME='销售部') │
│ ISRT EMPLOYEE(EMP_NAME='李四', ...) │
│ │
└─────────────────────────────────────────────────────────────────┘
删除操作
层次模型的删除规则:
┌─────────────────────────────────────────────────────────────────┐
│ 删除操作 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 规则:删除父节点会级联删除所有子节点 │
│ │
│ 删除"研发部"的影响: │
│ │
│ 删除前: 删除后: │
│ ┌────────┐ ┌────────┐ │
│ │ 公司 │ │ 公司 │ │
│ └───┬────┘ └───┬────┘ │
│ │ │ │
│ ┌─────┼─────┐ ┌─────┴─────┐ │
│ ↓ ↓ ↓ ↓ ↓ │
│ ┌────┐┌────┐┌────┐ ┌────┐ ┌────┐ │
│ │研发│|销售││财务│ │销售│ │财务│ │
│ └─┬──┘└────┘└────┘ └────┘ └────┘ │
│ │ │
│ ┌─┼─┐ 研发部及其所有员工被删除 │
│ ↓ ↓ ↓ │
│ ┌─┐┌─┐┌─┐ │
│ │A││B││C│ ← 员工也被级联删除 │
│ └─┘└─┘└─┘ │
│ │
│ 这是层次模型的重要特性:级联删除自动进行 │
│ │
└─────────────────────────────────────────────────────────────────┘
更新操作
层次模型的更新规则:
┌─────────────────────────────────────────────────────────────────┐
│ 更新操作 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 更新非关键属性 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 可以直接修改 │ │
│ │ 例如:修改员工的电话号码 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 更新父节点引用(更改所属部门) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 需要删除原记录,在新父节点下重新插入 │ │
│ │ 这是一个复杂操作 │ │
│ │ │ │
│ │ 员工调岗流程: │ │
│ │ 1. 从原部门删除员工记录 │ │
│ │ 2. 在新部门下插入员工记录 │ │
│ │ 3. 如果员工有下属,需要处理级联影响 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
操作的限制条件
| 操作 | 限制条件 | 说明 |
|---|---|---|
| 查询 | 必须从根开始导航 | 不能直接跳到任意节点 |
| 插入 | 子节点依赖父节点 | 必须先有父节点 |
| 删除 | 级联删除子节点 | 删除父节点=删除整个子树 |
| 更新 | 不能改变层次关系 | 改层次需删除重建 |
3.4 层次模型的数据约束
层次模型通过其结构特性自然地实现了多种数据完整性约束。
完整性约束
层次模型的完整性约束:
┌─────────────────────────────────────────────────────────────────┐
│ 完整性约束 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 实体完整性 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 每个记录类型必须有唯一标识 │ │
│ │ • 主键值不能为空 │ │
│ │ • 同一父节点下的子节点键值唯一 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 参照完整性(通过结构保证) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 子节点必须有对应的父节点 │ │
│ │ • 删除父节点时级联删除子节点 │ │
│ │ • 不存在"孤儿"记录问题 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 用户定义完整性 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 字段的数据类型约束 │ │
│ │ • 字段的取值范围约束 │ │
│ │ • 业务规则约束(需应用层实现) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
层次结构约束
层次结构的固有约束:
┌─────────────────────────────────────────────────────────────────┐
│ 结构约束 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 单根约束 │
│ 每棵层次树有且只有一个根节点 │
│ │
│ 2. 唯一父节点约束 │
│ 每个非根节点有且只有一个父节点 │
│ │
│ 3. 访问路径唯一约束 │
│ 从根到任意节点的路径是唯一的 │
│ │
│ 图示: │
│ │
│ ✗ 不允许的结构(多父): ✓ 允许的结构: │
│ │
│ A B A │
│ \ / /|\ │
│ \ / / | \ │
│ C B C D │
│ │
│ ✗ 不允许的结构(多根): ✓ 允许的结构(多棵树): │
│ │
│ A B (直接连接) A B (独立的树) │
│ | | 不允许 | | │
│ C D C D │
│ │
└─────────────────────────────────────────────────────────────────┘
唯一性约束
| 约束类型 | 描述 | 示例 |
|---|---|---|
| 键唯一性 | 同类型记录的键值不重复 | 部门编号唯一 |
| 层次内唯一 | 同一父节点下子节点键唯一 | 同部门员工工号唯一 |
| 序列键 | 子节点按序列号排序 | 按入职顺序编号 |
3.5 层次模型的优缺点
优点
层次模型的优势:
┌─────────────────────────────────────────────────────────────────┐
│ 优 点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 结构简单清晰 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 树形结构直观易懂 │ │
│ │ • 符合人类思维的层次概念 │ │
│ │ • 适合表示具有明确上下级关系的数据 │ │
│ │ • 学习和理解成本低 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 查询效率高 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 沿着固定路径访问,无需复杂计算 │ │
│ │ • 父子关系通过物理存储保证,访问速度快 │ │
│ │ • 适合层次遍历类查询 │ │
│ │ • 在特定场景下性能优于关系模型 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 数据完整性容易保证 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 结构本身保证参照完整性 │ │
│ │ • 级联删除自动进行 │ │
│ │ • 不会产生"孤儿"记录 │ │
│ │ • 一致性维护相对简单 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
缺点
层次模型的局限:
┌─────────────────────────────────────────────────────────────────┐
│ 缺 点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 结构缺乏灵活性 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 一旦设计好,难以修改结构 │ │
│ │ • 增加新的层次关系成本高 │ │
│ │ • 不适应频繁变化的业务需求 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 不能直接表示多对多联系 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 每个节点只能有一个父节点 │ │
│ │ • 表示M:N关系需要引入数据冗余 │ │
│ │ • 例如:学生选课(学生M:N课程)难以表示 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 数据冗余问题 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 处理M:N时需要复制数据 │ │
│ │ • 冗余导致数据不一致风险 │ │
│ │ • 存储空间浪费 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4. 操作复杂 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 查询必须从根开始导航 │ │
│ │ • 程序员需了解物理存储结构 │ │
│ │ • 数据独立性差 │ │
│ │ • 应用程序与数据结构紧耦合 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
优缺点对比总结:
| 方面 | 优点 | 缺点 |
|---|---|---|
| 结构 | 简单清晰 | 不灵活 |
| 性能 | 层次查询快 | 跨分支查询难 |
| 关系 | 1:N关系直观 | 不支持M:N |
| 独立性 | --- | 数据独立性差 |
| 维护 | 完整性好 | 修改结构困难 |
3.6 层次数据库实例
IBM IMS数据库介绍
IBM IMS 概况:
┌─────────────────────────────────────────────────────────────────┐
│ IBM IMS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 基本信息: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 全称:Information Management System │ │
│ │ 发布:1968年(已运行50+年) │ │
│ │ 开发商:IBM │ │
│ │ 类型:层次数据库管理系统 │ │
│ │ 平台:IBM大型机(Mainframe) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 核心组件: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • IMS DB:数据库管理器 │ │
│ │ • IMS TM:事务管理器 │ │
│ │ • IMS Connect:网络连接组件 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 数据语言(DL/I): │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ GU - Get Unique(获取唯一记录) │ │
│ │ GN - Get Next(获取下一条) │ │
│ │ GNP - Get Next within Parent(获取同父下一条) │ │
│ │ ISRT - Insert(插入) │ │
│ │ DLET - Delete(删除) │ │
│ │ REPL - Replace(更新) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 现状: │
│ • 全球超过95%的财富500强企业仍在使用IMS │
│ • 处理着银行、保险等关键业务数据 │
│ • 日处理事务量可达数十亿 │
│ │
└─────────────────────────────────────────────────────────────────┘
层次数据库的应用场景
| 场景 | 描述 | 实例 |
|---|---|---|
| 银行核心系统 | 账户-交易的层次关系 | 客户→账户→交易记录 |
| 航空订票 | 航班-座位的层次结构 | 航班→舱位→座位 |
| 制造业BOM | 产品-部件的层次关系 | 产品→组件→零件 |
| 医疗记录 | 患者-病历的层次结构 | 患者→就诊→检查 |
现代应用中的层次结构
现代技术中的层次思想:
┌─────────────────────────────────────────────────────────────────┐
│ 层次结构的现代应用 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. XML文档 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ <company> │ │
│ │ <department name="研发部"> │ │
│ │ <employee>张三</employee> │ │
│ │ <employee>李四</employee> │ │
│ │ </department> │ │
│ │ </company> │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. JSON文档 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ { │ │
│ │ "company": { │ │
│ │ "departments": [ │ │
│ │ { "name": "研发部", │ │
│ │ "employees": ["张三", "李四"] } │ │
│ │ ] │ │
│ │ } │ │
│ │ } │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 文件系统 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ C:\ │ │
│ │ ├── Program Files\ │ │
│ │ │ ├── App1\ │ │
│ │ │ └── App2\ │ │
│ │ ├── Users\ │ │
│ │ └── Windows\ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4. MongoDB等文档数据库 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 文档天然具有嵌套的层次结构 │ │
│ │ 支持嵌入式文档和数组 │ │
│ │ 继承了层次模型的直观性 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
层次思想的现代演变:
| 技术 | 层次特征 | 与传统层次模型的区别 |
|---|---|---|
| XML/DOM | 树形结构 | 更灵活的schema |
| JSON | 嵌套对象 | 无严格约束 |
| NoSQL文档库 | 嵌入式文档 | 支持复杂查询 |
| 图数据库 | 可表示层次 | 也支持M:N关系 |
第四章 网状模型
网状模型是在层次模型基础上发展起来的数据模型,克服了层次模型不能表示多对多关系的限制,曾是关系模型出现前最有影响力的数据模型。
4.1 网状模型概述
网状模型的定义
网状模型(Network Model)是用有向图结构来表示实体及其联系的数据模型。与层次模型不同,网状模型允许一个节点有多个父节点,从而能够表示更复杂的数据关系。
网状模型的基本概念:
┌─────────────────────────────────────────────────────────────────┐
│ 网状模型结构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 层次模型(树形): 网状模型(图形): │
│ │
│ A A ────────┐ │
│ /|\ /|\ | │
│ / | \ / | \ | │
│ B C D B C D | │
│ \ | / | │
│ 每个节点只有一个父节点 \ | / ↓ │
│ E ←───────┘ │
│ │
│ E有多个父节点(B、C、D、A) │
│ │
│ 关键区别: │
│ • 层次模型:每个节点只能有一个父节点(树) │
│ • 网状模型:每个节点可以有多个父节点(图) │
│ │
└─────────────────────────────────────────────────────────────────┘
网状模型的起源
网状模型起源于CODASYL (Conference on Data Systems Languages)组织的工作,由其下属的DBTG(Database Task Group)制定标准。
网状模型的发展历程:
┌─────────────────────────────────────────────────────────────────┐
│ 发展历程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1965年 ───────────────────────────────────────────────────── │
│ │ GE(通用电气)开发IDS(Integrated Data Store) │
│ │ Charles Bachman 主持设计 │
│ │ 被认为是第一个网状数据库系统 │
│ ↓ │
│ 1969年 ───────────────────────────────────────────────────── │
│ │ CODASYL组织成立DBTG │
│ │ 开始制定网状数据库标准 │
│ ↓ │
│ 1971年 ───────────────────────────────────────────────────── │
│ │ DBTG发布首个网状模型报告 │
│ │ 定义了网状模型的核心概念和语言 │
│ ↓ │
│ 1973年 ───────────────────────────────────────────────────── │
│ │ Charles Bachman获得图灵奖 │
│ │ 表彰其在数据库技术方面的贡献 │
│ ↓ │
│ 1970s-1980s ──────────────────────────────────────────────── │
│ 多个商用网状数据库系统发布 │
│ IDMS、DMS-1100等 │
│ │
└─────────────────────────────────────────────────────────────────┘
重要人物与事件:
| 年份 | 事件 | 贡献者 |
|---|---|---|
| 1965 | IDS数据库诞生 | Charles Bachman |
| 1969 | DBTG成立 | CODASYL组织 |
| 1971 | DBTG报告发布 | DBTG工作组 |
| 1973 | 图灵奖 | Charles Bachman |
网状模型与层次模型的关系
网状模型与层次模型对比:
┌─────────────────────────────────────────────────────────────────┐
│ 模型对比 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 联系: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 都属于格式化数据模型 │ │
│ │ • 都使用导航式访问方式 │ │
│ │ • 都需要通过指针链接记录 │ │
│ │ • 层次模型是网状模型的特例(无环的连通图) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 区别: │
│ ┌──────────────────┬──────────────────┬──────────────────┐ │
│ │ 特性 │ 层次模型 │ 网状模型 │ │
│ ├──────────────────┼──────────────────┼──────────────────┤ │
│ │ 数据结构 │ 树形结构 │ 有向图 │ │
│ │ 父节点数量 │ 最多一个 │ 可以有多个 │ │
│ │ M:N关系 │ 不能直接表示 │ 可以直接表示 │ │
│ │ 复杂度 │ 较简单 │ 较复杂 │ │
│ │ 访问灵活性 │ 较低 │ 较高 │ │
│ └──────────────────┴──────────────────┴──────────────────┘ │
│ │
│ 演进关系: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 层次模型 ──(扩展)──→ 网状模型 ──(简化)──→ 关系模型 │ │
│ │ (1968) (1969) (1970) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
4.2 网状模型的数据结构
有向图结构
网状模型的有向图表示:
┌─────────────────────────────────────────────────────────────────┐
│ 有向图结构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 示例:学生选课系统 │
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ 学生 │ │ 课程 │ │
│ │ Student │ │ Course │ │
│ └────┬────┘ └────┬────┘ │
│ │ │ │
│ │ 选课Set │ 授课Set │
│ ↓ ↓ │
│ ┌────────────────────────────────────┐ │
│ │ 选课记录 │ │
│ │ Enrollment │ │
│ └────────────────────────────────────┘ │
│ ↑ │
│ │ 成绩Set │
│ ┌─────┴─────┐ │
│ │ 教师 │ │
│ │ Teacher │ │
│ └───────────┘ │
│ │
│ 特点: │
│ • 节点代表记录类型 │
│ • 有向边代表记录之间的联系(系) │
│ • 一个记录可以参与多个系 │
│ • 可以有环,可以表示复杂关系 │
│ │
└─────────────────────────────────────────────────────────────────┘
记录类型(Record Type)
记录类型的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 记录类型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 定义:记录类型是具有相同属性集合的记录的集合 │
│ 类似于关系模型中的"表"或面向对象中的"类" │
│ │
│ 示例: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 记录类型:Student(学生) │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │ 学号 (Key) │ 姓名 │ 年龄 │ 专业 │ 入学年份 │ │
│ ├─────────────┼───────┼──────┼───────┼──────────────────┤ │
│ │ S001 │ 张三 │ 20 │ 计算机│ 2023 │ │
│ │ S002 │ 李四 │ 21 │ 数学 │ 2022 │ │
│ │ S003 │ 王五 │ 19 │ 物理 │ 2024 │ │
│ └─────────────┴───────┴──────┴───────┴──────────────────┘ │
│ │
│ 记录类型的组成: │
│ • 记录名:标识记录类型 │
│ • 数据项:组成记录的字段(属性) │
│ • 记录键:唯一标识记录的字段(组合) │
│ │
└─────────────────────────────────────────────────────────────────┘
系类型(Set Type)
系类型是网状模型的核心概念:
┌─────────────────────────────────────────────────────────────────┐
│ 系类型(Set Type) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 定义:系类型定义了两个记录类型之间的1:N联系 │
│ │
│ 系的组成: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌─────────────┐ │ │
│ │ │ 属主记录 │ Owner Record │ │
│ │ │ (父节点) │ 只能有一个属主类型 │ │
│ │ └──────┬──────┘ │ │
│ │ │ 系名 │ │
│ │ ↓ │ │
│ │ ┌─────────────┐ │ │
│ │ │ 成员记录 │ Member Record │ │
│ │ │ (子节点) │ 可以有多个成员 │ │
│ │ └─────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 示例:"部门-员工"系 │
│ │
│ ┌─────────────┐ │
│ │ Department │ ← 属主记录类型 │
│ │ (研发部) │ │
│ └──────┬───────┘ │
│ │ Dept_Emp(系名) │
│ ↓ │
│ ┌──────────────────────────────────────┐ │
│ │ Employee │ Employee │ Employee │ ← 成员记录 │
│ │ (张三) │ (李四) │ (王五) │ │
│ └──────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
成员记录与属主记录
| 概念 | 说明 | 数量限制 |
|---|---|---|
| 属主记录(Owner) | 系中的"父"记录 | 每个系只能有一个属主类型 |
| 成员记录(Member) | 系中的"子"记录 | 每个系只能有一个成员类型 |
| 系实例(Set Instance) | 一个属主记录+多个成员记录 | 一个属主可对应多个成员 |
4.3 网状模型的数据操作
导航式访问
网状模型的导航方式:
┌─────────────────────────────────────────────────────────────────┐
│ 导航式访问 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 与层次模型类似,网状模型也使用导航式访问 │
│ 但由于图结构,访问路径更加灵活 │
│ │
│ 访问方式: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. 通过键值定位记录 │ │
│ │ 2. 沿着系的链接访问相关记录 │ │
│ │ 3. 可以从多个入口点访问同一记录 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ DML命令示例(CODASYL): │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ FIND - 定位记录 │ │
│ │ GET - 获取当前记录 │ │
│ │ FIND NEXT - 找下一条记录 │ │
│ │ FIND OWNER - 找属主记录 │ │
│ │ FIND FIRST - 找第一个成员 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
查询、插入、删除、更新操作
网状模型的CRUD操作:
┌─────────────────────────────────────────────────────────────────┐
│ 数据操作 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 查询(FIND + GET): │
│ FIND FIRST Employee WITHIN Dept_Emp │
│ GET Employee │
│ -- 查找部门中第一个员工 │
│ │
│ 插入(STORE + CONNECT): │
│ MOVE "S004" TO Emp_ID │
│ MOVE "赵六" TO Emp_Name │
│ STORE Employee │
│ CONNECT Employee TO Dept_Emp │
│ -- 插入新员工并连接到部门 │
│ │
│ 删除(DISCONNECT + ERASE): │
│ FIND Employee WHERE Emp_ID = "S001" │
│ DISCONNECT Employee FROM Dept_Emp │
│ ERASE Employee │
│ -- 先断开联系,再删除记录 │
│ │
│ 更新(MODIFY): │
│ FIND Employee WHERE Emp_ID = "S002" │
│ GET Employee │
│ MOVE "已婚" TO Emp_Status │
│ MODIFY Employee │
│ -- 修改员工状态 │
│ │
└─────────────────────────────────────────────────────────────────┘
4.4 网状模型的数据约束
成员约束(Membership Constraint)
成员记录参与系的约束:
┌─────────────────────────────────────────────────────────────────┐
│ 成员约束类型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. AUTOMATIC(自动) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 成员记录存储时自动加入系 │ │
│ │ 不需要显式CONNECT操作 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. MANUAL(手动) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 成员记录存储后需要手动CONNECT到系 │ │
│ │ 提供更大的灵活性 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. MANDATORY(强制) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 成员记录必须永远属于某个系 │ │
│ │ 不能DISCONNECT,除非删除 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 4. OPTIONAL(可选) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 成员记录可以不属于任何系 │ │
│ │ 可以DISCONNECT后独立存在 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
插入/删除约束
| 约束类型 | 插入行为 | 删除行为 |
|---|---|---|
| AUTOMATIC MANDATORY | 自动加入系 | 必须先删除所有成员 |
| AUTOMATIC OPTIONAL | 自动加入系 | 成员可变为独立 |
| MANUAL MANDATORY | 手动加入系 | 不能独立存在 |
| MANUAL OPTIONAL | 手动加入系 | 可以独立存在 |
4.5 网状模型的优缺点
优点
网状模型的优势:
┌─────────────────────────────────────────────────────────────────┐
│ 优 点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 能表示复杂的数据关系 │
│ • 突破了层次模型的树形限制 │
│ • 可以表示实体间的多种联系 │
│ │
│ 2. 支持多对多联系 │
│ • 通过引入中间记录类型实现M:N │
│ • 比层次模型更接近现实世界 │
│ │
│ 3. 存取效率较高 │
│ • 通过指针直接访问 │
│ • 避免了连接操作的开销 │
│ │
│ 4. 数据完整性控制 │
│ • 成员约束机制保证数据一致性 │
│ • 系结构强制执行业务规则 │
│ │
└─────────────────────────────────────────────────────────────────┘
缺点
网状模型的局限:
┌─────────────────────────────────────────────────────────────────┐
│ 缺 点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 结构复杂 │
│ • 系和记录的组合使结构难以理解 │
│ • 数据库设计复杂度高 │
│ │
│ 2. 用户难以使用 │
│ • 需要了解底层数据结构 │
│ • 导航式操作学习曲线陡峭 │
│ • 查询语言不直观 │
│ │
│ 3. 数据独立性差 │
│ • 程序依赖于物理存储结构 │
│ • 结构改变需修改应用程序 │
│ • 维护成本高 │
│ │
│ 4. 缺乏标准化 │
│ • 各厂商实现差异大 │
│ • 可移植性差 │
│ │
└─────────────────────────────────────────────────────────────────┘
优缺点总结:
| 方面 | 优点 | 缺点 |
|---|---|---|
| 表达能力 | 能表示M:N关系 | 概念复杂 |
| 性能 | 指针访问效率高 | 指针维护开销 |
| 使用 | --- | 学习成本高 |
| 独立性 | --- | 物理依赖强 |
4.6 网状数据库实例
IDMS数据库介绍
IDMS概况:
┌─────────────────────────────────────────────────────────────────┐
│ IDMS数据库 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 基本信息: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 全称:Integrated Database Management System │ │
│ │ 开发商:Cullinane Corporation(后被CA收购) │ │
│ │ 首发:1971年 │ │
│ │ 标准:基于CODASYL DBTG规范 │ │
│ │ 平台:IBM大型机 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 特点: │
│ • 最成功的商用网状数据库之一 │
│ • 支持高事务处理能力 │
│ • 提供完整的系和记录管理 │
│ • 至今仍在一些遗留系统中运行 │
│ │
└─────────────────────────────────────────────────────────────────┘
网状数据库的历史地位
| 时期 | 地位 | 说明 |
|---|---|---|
| 1970s | 主流技术 | 与层次模型并驾齐驱 |
| 1980s | 逐渐衰落 | 关系模型开始主导 |
| 1990s | 遗留系统 | 新项目很少采用 |
| 现在 | 技术遗产 | 仅存在于特定领域 |
网状模型的现代影响
网状模型对现代技术的影响:
┌─────────────────────────────────────────────────────────────────┐
│ 现代技术中的影响 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 图数据库(Graph Database) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • Neo4j、OrientDB等继承了图结构思想 │ │
│ │ • 节点和边的概念来自网状模型 │ │
│ │ • 但提供了更现代的查询语言(如Cypher) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 对象-关系映射(ORM) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 对象之间的引用关系类似于网状模型的系 │ │
│ │ • 导航式访问模式被保留 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 知识图谱(Knowledge Graph) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 实体和关系的网状结构 │ │
│ │ • 用于搜索引擎、推荐系统 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 对比:网状模型 vs 现代图数据库 │
│ ┌──────────────────┬──────────────────┬──────────────────┐ │
│ │ 特性 │ 网状模型 │ 图数据库 │ │
│ ├──────────────────┼──────────────────┼──────────────────┤ │
│ │ 查询语言 │ DML/导航式 │ Cypher/声明式 │ │
│ │ 灵活性 │ 结构固定 │ Schema-free │ │
│ │ 应用场景 │ 事务处理 │ 图分析/社交 │ │
│ └──────────────────┴──────────────────┴──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
第五章 关系模型
关系模型是目前应用最广泛的数据库模型,由E.F. Codd于1970年提出,彻底改变了数据库技术的发展方向,成为现代数据库系统的理论基础。
5.1 关系模型概述
关系模型的定义
**关系模型(Relational Model)是用二维表(关系)**的形式来组织和存储数据的逻辑数据模型。它将数据看作由若干个关系组成,每个关系是一个二维表,表中的行代表实体实例,列代表实体属性。
关系模型的核心思想:
┌─────────────────────────────────────────────────────────────────┐
│ 关系模型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 核心理念:用简单的二维表表示所有数据及其联系 │
│ │
│ 示例:学生表(Students) │
│ ┌─────────┬────────┬─────┬──────────┬──────────┐ │
│ │ 学号 │ 姓名 │ 年龄│ 性别 │ 专业 │ │
│ │(主键) │ │ │ │ │ │
│ ├─────────┼────────┼─────┼──────────┼──────────┤ │
│ │ S001 │ 张三 │ 20 │ 男 │ 计算机 │ │
│ │ S002 │ 李四 │ 21 │ 女 │ 数学 │ │
│ │ S003 │ 王五 │ 19 │ 男 │ 物理 │ │
│ └─────────┴────────┴─────┴──────────┴──────────┘ │
│ │
│ 表 = 关系(Relation) │
│ 行 = 元组(Tuple) │
│ 列 = 属性(Attribute) │
│ │
└─────────────────────────────────────────────────────────────────┘
关系模型的起源
关系模型的诞生历程:
┌─────────────────────────────────────────────────────────────────┐
│ 发展历程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1970年 ───────────────────────────────────────────────────── │
│ │ E.F. Codd 在 IBM 发表论文: │
│ │ "A Relational Model of Data for Large Shared Data Banks" │
│ │ 奠定了关系模型的理论基础 │
│ ↓ │
│ 1974年 ───────────────────────────────────────────────────── │
│ │ IBM 开发 System R 原型(关系数据库实验系统) │
│ │ 发明 SQL 语言 │
│ ↓ │
│ 1976年 ───────────────────────────────────────────────────── │
│ │ UC Berkeley 开发 Ingres(后来 PostgreSQL 的前身) │
│ ↓ │
│ 1979年 ───────────────────────────────────────────────────── │
│ │ Oracle 发布首个商用关系数据库 │
│ ↓ │
│ 1981年 ───────────────────────────────────────────────────── │
│ │ E.F. Codd 获得图灵奖 │
│ ↓ │
│ 1986年 ───────────────────────────────────────────────────── │
│ SQL 成为 ANSI/ISO 标准 │
│ │
└─────────────────────────────────────────────────────────────────┘
E.F. Codd的贡献:
| 贡献 | 说明 |
|---|---|
| 关系模型理论 | 用集合论和谓词逻辑描述数据 |
| 关系代数 | 定义了关系操作的数学基础 |
| 规范化理论 | 提出1NF、2NF、3NF |
| 12条准则 | 定义关系数据库的标准 |
关系模型的革命性意义
关系模型的革命性意义:
┌─────────────────────────────────────────────────────────────────┐
│ 革命性意义 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 数据独立性 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 物理数据独立性:存储方式改变不影响应用程序 │ │
│ │ • 逻辑数据独立性:逻辑结构改变对应用透明 │ │
│ │ • 程序员无需了解底层存储细节 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 声明式查询 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 用户说明"要什么",不用说明"怎么做" │ │
│ │ • 由系统优化器决定执行策略 │ │
│ │ • 大大简化了数据访问 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 坚实的数学基础 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 基于集合论和一阶谓词逻辑 │ │
│ │ • 提供形式化的推理和证明 │ │
│ │ • 查询优化有理论依据 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 对比: │
│ ┌──────────────────┬──────────────────┬──────────────────┐ │
│ │ 特性 │ 层次/网状模型 │ 关系模型 │ │
│ ├──────────────────┼──────────────────┼──────────────────┤ │
│ │ 访问方式 │ 导航式(过程式) │ 声明式 │ │
│ │ 数据独立性 │ 低 │ 高 │ │
│ │ 用户友好性 │ 低 │ 高 │ │
│ │ 理论基础 │ 弱 │ 强 │ │
│ └──────────────────┴──────────────────┴──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
5.2 关系模型的基本概念
5.2.1 关系(Relation)
关系的定义
在关系模型中,**关系(Relation)**是一个满足特定规范的二维表。形式上,关系是笛卡尔积的一个子集。
关系的形式化定义:
┌─────────────────────────────────────────────────────────────────┐
│ 关系的定义 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 设 D₁, D₂, ..., Dₙ 为 n 个域 │
│ 关系 R 是 D₁ × D₂ × ... × Dₙ 的子集 │
│ 记作:R ⊆ D₁ × D₂ × ... × Dₙ │
│ │
│ 其中: │
│ • Dᵢ 是第 i 个属性的取值范围(域) │
│ • n 称为关系的度(Degree)或元数 │
│ • 关系中元组的个数称为基数(Cardinality) │
│ │
│ 示例: │
│ D₁ = {张三, 李四} -- 学生姓名域 │
│ D₂ = {20, 21, 22} -- 年龄域 │
│ D₃ = {计算机, 数学} -- 专业域 │
│ │
│ 关系 Student = { (张三, 20, 计算机), │
│ (李四, 21, 数学) } │
│ │
└─────────────────────────────────────────────────────────────────┘
关系的性质
| 性质 | 说明 | 意义 |
|---|---|---|
| 列是同质的 | 每列只能有一种类型的值 | 保证数据一致性 |
| 列顺序无关 | 列可以交换顺序 | 逻辑独立性 |
| 行顺序无关 | 行可以任意排列 | 集合语义 |
| 行唯一性 | 不能有重复的元组 | 集合定义要求 |
| 原子性 | 每个属性值不可再分 | 1NF基本要求 |
5.2.2 元组与属性
元组和属性的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 元组与属性 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 关系表示例: │
│ │
│ 属性(Attribute)/ 列(Column) │
│ ↓ ↓ ↓ ↓ ↓ │
│ ┌──────────────────────────────────────────────┐ │
│ │ 学号 │ 姓名 │ 年龄 │ 性别 │ 专业 │ │
│ ├──────────────────────────────────────────────┤ │
│ │ S001 │ 张三 │ 20 │ 男 │ 计算机 │ ← 元组(Tuple)│
│ │ S002 │ 李四 │ 21 │ 女 │ 数学 │ ← 行(Row) │
│ │ S003 │ 王五 │ 19 │ 男 │ 物理 │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ 术语对照: │
│ ┌────────────┬────────────┬────────────┐ │
│ │ 理论术语 │ 表格术语 │ 编程术语 │ │
│ ├────────────┼────────────┼────────────┤ │
│ │ 关系 │ 表 │ 记录集 │ │
│ │ 元组 │ 行 │ 记录 │ │
│ │ 属性 │ 列 │ 字段 │ │
│ │ 域 │ 数据类型 │ 类型 │ │
│ └────────────┴────────────┴────────────┘ │
│ │
│ 域(Domain):属性的取值范围 │
│ 例如:年龄域 = {1, 2, 3, ..., 150} │
│ 性别域 = {男, 女} │
│ │
└─────────────────────────────────────────────────────────────────┘
5.2.3 键(Key)
各种键的定义:
┌─────────────────────────────────────────────────────────────────┐
│ 键的类型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 超键(Super Key) │
│ 能唯一标识元组的属性集合(可能包含冗余属性) │
│ 示例:{学号}、{学号, 姓名}、{学号, 年龄} 都是超键 │
│ │
│ 2. 候选键(Candidate Key) │
│ 不含冗余属性的超键(最小超键) │
│ 示例:{学号}、{身份证号} 是候选键 │
│ {学号, 姓名} 不是(姓名是冗余的) │
│ │
│ 3. 主键(Primary Key) │
│ 从候选键中选定的一个,作为元组的唯一标识 │
│ 特点:唯一、非空 │
│ 示例:选择"学号"作为主键 │
│ │
│ 4. 外键(Foreign Key) │
│ 一个关系中的属性,引用另一个关系的主键 │
│ 用于建立关系之间的联系 │
│ │
│ 5. 代理键(Surrogate Key) │
│ 系统自动生成的无业务含义的键 │
│ 示例:自增ID、UUID │
│ │
└─────────────────────────────────────────────────────────────────┘
外键示例:
sql
-- 学生表
CREATE TABLE Students (
student_id VARCHAR(10) PRIMARY KEY, -- 主键
name VARCHAR(50),
major_id INT -- 外键,引用专业表
);
-- 专业表
CREATE TABLE Majors (
major_id INT PRIMARY KEY, -- 主键
major_name VARCHAR(50)
);
-- 建立外键关系
ALTER TABLE Students
ADD FOREIGN KEY (major_id) REFERENCES Majors(major_id);
5.3 关系模型的数据结构
关系模式(Relation Schema)
关系模式的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 关系模式 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 关系模式 = 关系的结构定义(类似于类/类型) │
│ 关系实例 = 关系在某时刻的具体数据(类似于对象/值) │
│ │
│ 形式表示:R(A₁, A₂, ..., Aₙ) │
│ 其中 R 是关系名,Aᵢ 是属性名 │
│ │
│ 示例: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 关系模式(Schema): │ │
│ │ Student(学号, 姓名, 年龄, 性别, 专业) │ │
│ │ │ │
│ │ 关系实例(Instance): │ │
│ │ ┌───────┬──────┬──────┬──────┬────────┐ │ │
│ │ │ 学号 │ 姓名 │ 年龄 │ 性别 │ 专业 │ │ │
│ │ ├───────┼──────┼──────┼──────┼────────┤ │ │
│ │ │ S001 │ 张三 │ 20 │ 男 │ 计算机 │ │ │
│ │ │ S002 │ 李四 │ 21 │ 女 │ 数学 │ │ │
│ │ └───────┴──────┴──────┴──────┴────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 关系数据库模式 = 多个关系模式 + 完整性约束 │
│ │
└─────────────────────────────────────────────────────────────────┘
5.4 关系模型的数据操作
关系代数
关系代数是关系模型的数学基础,定义了一组关系运算。
关系代数的基本运算:
┌─────────────────────────────────────────────────────────────────┐
│ 关系代数 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 传统集合运算: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 并(Union): R ∪ S │ │
│ │ 差(Difference): R - S │ │
│ │ 交(Intersection): R ∩ S │ │
│ │ 笛卡尔积: R × S │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 专门的关系运算: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 选择(Selection): σ_条件(R) │ │
│ │ 投影(Projection): π_属性列表(R) │ │
│ │ 连接(Join): R ⋈ S │ │
│ │ 除(Division): R ÷ S │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
运算示例:
| 运算 | 符号 | SQL等价 | 示例 |
|---|---|---|---|
| 选择 | σ | WHERE | σ_年龄>20(Student) → 年龄大于20的学生 |
| 投影 | π | SELECT列 | π_姓名,专业(Student) → 只取姓名和专业 |
| 并 | ∪ | UNION | R ∪ S → 两个关系的所有元组 |
| 差 | - | EXCEPT | R - S → R中有但S中没有的元组 |
| 连接 | ⋈ | JOIN | Student ⋈ Course → 学生和课程的连接 |
关系演算
关系演算的两种形式:
┌─────────────────────────────────────────────────────────────────┐
│ 关系演算 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 元组关系演算(Tuple Relational Calculus) │
│ 以元组为变量 │
│ 示例:{ t | Student(t) ∧ t.年龄 > 20 } │
│ 含义:所有年龄大于20的学生元组 │
│ │
│ 2. 域关系演算(Domain Relational Calculus) │
│ 以属性域为变量 │
│ 示例:{ <姓名, 专业> | ∃年龄 (Student(姓名,年龄,专业) │
│ ∧ 年龄 > 20) } │
│ 含义:年龄大于20的学生的姓名和专业 │
│ │
│ 关系代数与关系演算的等价性: │
│ 任何可用关系代数表示的查询都可以用关系演算表示,反之亦然 │
│ │
└─────────────────────────────────────────────────────────────────┘
SQL语言
SQL(Structured Query Language)是关系模型的标准查询语言。
sql
-- SQL基本操作示例
-- 选择(WHERE)
SELECT * FROM Students WHERE age > 20;
-- 投影(SELECT列)
SELECT name, major FROM Students;
-- 连接(JOIN)
SELECT s.name, c.course_name
FROM Students s
JOIN Enrollments e ON s.student_id = e.student_id
JOIN Courses c ON e.course_id = c.course_id;
-- 聚合(GROUP BY)
SELECT major, COUNT(*) as student_count
FROM Students
GROUP BY major;
-- 子查询
SELECT * FROM Students
WHERE major_id IN (SELECT major_id FROM Majors WHERE faculty = '理学院');
5.5 关系模型的数据约束
关系模型的三类完整性约束:
┌─────────────────────────────────────────────────────────────────┐
│ 完整性约束 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 实体完整性(Entity Integrity) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 主键不能为空(NOT NULL) │ │
│ │ • 主键值必须唯一 │ │
│ │ • 保证每个实体可以被唯一识别 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 2. 参照完整性(Referential Integrity) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • 外键值必须在被引用表中存在,或者为空 │ │
│ │ • 保证关系之间引用的有效性 │ │
│ │ • 违反时的处理:RESTRICT/CASCADE/SET NULL │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 3. 用户定义完整性 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ • CHECK约束:限制属性的取值范围 │ │
│ │ • UNIQUE约束:保证属性值唯一 │ │
│ │ • 触发器:自定义业务规则 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
约束示例:
sql
CREATE TABLE Students (
student_id VARCHAR(10) PRIMARY KEY, -- 实体完整性
name VARCHAR(50) NOT NULL,
age INT CHECK (age >= 0 AND age <= 150), -- 用户定义完整性
email VARCHAR(100) UNIQUE, -- 用户定义完整性
major_id INT REFERENCES Majors(major_id) -- 参照完整性
ON DELETE SET NULL
ON UPDATE CASCADE
);
5.6 关系规范化理论
函数依赖
函数依赖的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 函数依赖 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 定义:设 R(U) 是属性集U上的关系模式,X和Y是U的子集 │
│ 如果对于R的任意实例r,当两个元组在X上的值相同时, │
│ 它们在Y上的值也必然相同,则称Y函数依赖于X,记作X→Y │
│ │
│ 示例: │
│ 学号 → 姓名 (学号决定姓名) │
│ 学号 → 年龄 (学号决定年龄) │
│ (学号, 课程号) → 成绩 (学号和课程号共同决定成绩) │
│ │
│ 函数依赖的类型: │
│ • 完全函数依赖:Y完全依赖于X的全部,X的任何真子集不能决定Y │
│ • 部分函数依赖:Y依赖于X的一部分 │
│ • 传递函数依赖:X→Y, Y→Z,则X传递决定Z │
│ │
└─────────────────────────────────────────────────────────────────┘
范式概述
范式的层级:
┌─────────────────────────────────────────────────────────────────┐
│ 范式层级 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1NF ⊂ 2NF ⊂ 3NF ⊂ BCNF ⊂ 4NF ⊂ 5NF │
│ │
│ 每个范式都是在前一范式基础上增加约束 │
│ 范式越高,数据冗余越少,但查询可能需要更多连接 │
│ │
└─────────────────────────────────────────────────────────────────┘
| 范式 | 核心要求 | 解决的问题 |
|---|---|---|
| 1NF | 属性值是原子的 | 消除重复组 |
| 2NF | 消除非主属性对键的部分依赖 | 消除部分依赖造成的冗余 |
| 3NF | 消除非主属性对键的传递依赖 | 消除传递依赖造成的冗余 |
| BCNF | 所有决定因素都是候选键 | 消除主属性对键的依赖 |
| 4NF | 消除非平凡多值依赖 | 消除多值依赖冗余 |
| 5NF | 消除连接依赖 | 消除连接依赖冗余 |
规范化与反规范化
规范化与反规范化的权衡:
┌─────────────────────────────────────────────────────────────────┐
│ 权衡考虑 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 规范化 反规范化 │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ ✓ 减少数据冗余 │ │ ✓ 提高查询性能 │ │
│ │ ✓ 避免更新异常 │ │ ✓ 减少连接操作 │ │
│ │ ✓ 保证数据一致性 │ │ ✓ 简化查询语句 │ │
│ │ ✗ 需要更多的连接 │ │ ✗ 增加数据冗余 │ │
│ │ ✗ 可能影响查询性能 │ │ ✗ 更新可能不一致 │ │
│ └──────────────────────┘ └──────────────────────┘ │
│ │
│ 实际应用建议: │
│ • OLTP系统:倾向于规范化,保证数据一致性 │
│ • OLAP系统:适度反规范化,提高查询性能 │
│ • 通常3NF或BCNF是较好的平衡点 │
│ │
└─────────────────────────────────────────────────────────────────┘
5.7 关系模型的优缺点
优点
关系模型的优势:
┌─────────────────────────────────────────────────────────────────┐
│ 优 点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 结构简单 │
│ • 用户和程序员易于理解和使用 │
│ • 数据以直观的表格形式呈现 │
│ │
│ 2. 数据独立性高 │
│ • 物理存储与逻辑结构分离 │
│ • 应用程序不依赖于存储细节 │
│ │
│ 3. 有坚实的数学基础 │
│ • 基于集合论和谓词逻辑 │
│ • 查询优化有理论支持 │
│ │
│ 4. SQL标准化 │
│ • 统一的查询语言 │
│ • 跨平台可移植性好 │
│ • 生态系统完善 │
│ │
└─────────────────────────────────────────────────────────────────┘
缺点
关系模型的局限:
┌─────────────────────────────────────────────────────────────────┐
│ 缺 点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 查询效率问题 │
│ • 复杂查询需要多表连接 │
│ • 大数据量时性能可能下降 │
│ │
│ 2. 不适合复杂对象 │
│ • 难以表示嵌套结构 │
│ • 不支持自定义数据类型 │
│ • 多媒体数据处理能力弱 │
│ │
│ 3. 阻抗不匹配问题 │
│ • 面向对象语言与关系模型的概念差距 │
│ • 需要ORM框架进行转换 │
│ │
│ 4. 扩展性限制 │
│ • 垂直扩展能力有限 │
│ • 分布式环境下水平扩展困难 │
│ │
└─────────────────────────────────────────────────────────────────┘
5.8 主流关系数据库
主流关系数据库对比:
┌──────────────┬──────────────────────────────────────────────────┐
│ 数据库 │ 特点 │
├──────────────┼──────────────────────────────────────────────────┤
│ │ • 企业级数据库的代表 │
│ Oracle │ • 功能最完整,性能强劲 │
│ │ • 成本高,适合大型企业 │
├──────────────┼──────────────────────────────────────────────────┤
│ │ • 最流行的开源数据库 │
│ MySQL │ • 简单易用,社区活跃 │
│ │ • 适合Web应用 │
├──────────────┼──────────────────────────────────────────────────┤
│ │ • 最先进的开源数据库 │
│ PostgreSQL │ • 功能丰富,支持扩展 │
│ │ • 适合复杂查询和GIS应用 │
├──────────────┼──────────────────────────────────────────────────┤
│ │ • 微软的企业数据库 │
│ SQL Server │ • 与Windows生态集成好 │
│ │ • BI和分析功能强大 │
├──────────────┼──────────────────────────────────────────────────┤
│ │ • 轻量级嵌入式数据库 │
│ SQLite │ • 零配置,无服务器 │
│ │ • 适合移动应用和小型项目 │
└──────────────┴──────────────────────────────────────────────────┘
第六章 面向对象模型
面向对象模型将面向对象编程的概念引入数据库领域,旨在解决关系模型在处理复杂数据结构时的局限性,为复杂应用提供更自然的数据建模方式。
6.1 面向对象模型概述
面向对象模型的定义
**面向对象数据模型(Object-Oriented Data Model,OODM)**是将面向对象编程语言的概念(对象、类、继承、封装、多态)应用于数据库系统的数据模型。
面向对象模型的核心概念:
┌─────────────────────────────────────────────────────────────────┐
│ 面向对象模型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 核心理念:数据和操作封装在对象中 │
│ │
│ 关系模型: 面向对象模型: │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ │ 表(Students) │ │ 类(Student) │ │
│ ├────────────────────┤ ├────────────────────┤ │
│ │ 学号│姓名│年龄│专业│ │ 属性(数据): │ │
│ │────│────│────│────│ │ - 学号 │ │
│ │ 数据│数据│数据│数据│ │ - 姓名 │ │
│ └────────────────────┘ │ - 年龄 │ │
│ + 外部SQL操作 │ 方法(行为): │ │
│ │ - 选课() │ │
│ │ - 获取成绩() │ │
│ └────────────────────┘ │
│ 数据+行为封装在一起 │
│ │
└─────────────────────────────────────────────────────────────────┘
面向对象模型的起源
发展历程:
┌─────────────────────────────────────────────────────────────────┐
│ 发展历程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1980s中期 ─────────────────────────────────────────────────── │
│ │ 面向对象数据库概念提出 │
│ │ Smalltalk等OO语言影响 │
│ ↓ │
│ 1989年 ───────────────────────────────────────────────────── │
│ │ ODMG(Object Data Management Group)成立 │
│ │ 开始制定面向对象数据库标准 │
│ ↓ │
│ 1993年 ───────────────────────────────────────────────────── │
│ │ ODMG-93标准发布 │
│ │ 定义ODL(对象定义语言)和OQL(对象查询语言) │
│ ↓ │
│ 1997年-2000年 ────────────────────────────────────────────── │
│ │ ODMG 2.0、ODMG 3.0发布 │
│ │ 标准逐渐完善 │
│ ↓ │
│ 2000s ────────────────────────────────────────────────────── │
│ 对象关系数据库兴起 │
│ 纯面向对象数据库市场萎缩 │
│ │
└─────────────────────────────────────────────────────────────────┘
面向对象模型的产生背景
| 背景 | 说明 |
|---|---|
| 关系模型的局限 | 难以表示复杂对象、嵌套结构 |
| OOP语言流行 | Java、C++等语言广泛使用 |
| 阻抗不匹配 | 对象与表的转换开销 |
| 新应用需求 | CAD/CAM、GIS、多媒体等 |
6.2 面向对象的基本概念
6.2.1 对象(Object)
对象的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 对象 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 定义:对象是现实世界实体的抽象,包含状态(属性)和行为(方法) │
│ │
│ 对象的组成: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Student对象 │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │ OID: OID_12345 (对象标识,系统唯一) │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │ 状态(属性): │ │
│ │ - studentId = "S001" │ │
│ │ - name = "张三" │ │
│ │ - age = 20 │ │
│ │ - courses = [Course对象1, Course对象2] (复杂属性) │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │ 行为(方法): │ │
│ │ - enroll(course) │ │
│ │ - getGrade(course) │ │
│ │ - calculateGPA() │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 对象标识(OID): │
│ • 系统自动生成的唯一标识 │
│ • 不依赖于属性值(与主键不同) │
│ • 对象生命周期内不变 │
│ • 即使属性值完全相同,不同对象的OID也不同 │
│ │
└─────────────────────────────────────────────────────────────────┘
6.2.2 类(Class)
类的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 类 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 定义:类是具有相同属性和方法的对象的模板/蓝图 │
│ │
│ 类与对象的关系: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ 类(Class) 对象(Object) │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Student │ ──→ │ student1 │ │ │
│ │ │ (模板) │ 实例化 │ OID:001 │ │ │
│ │ ├──────────────┤ ├──────────────┤ │ │
│ │ │ -studentId │ ──→ │ student2 │ │ │
│ │ │ -name │ │ OID:002 │ │ │
│ │ │ -age │ ├──────────────┤ │ │
│ │ │ +enroll() │ ──→ │ student3 │ │ │
│ │ │ +getGrade() │ │ OID:003 │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 类层次结构(继承): │
│ Person │
│ ↑ │
│ ┌────────┴────────┐ │
│ Student Teacher │
│ ↑ │
│ GraduateStudent │
│ │
└─────────────────────────────────────────────────────────────────┘
6.2.3 继承(Inheritance)
继承的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 继承 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 单继承:一个子类只有一个直接父类 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Person │ │
│ │ ↑ │ │
│ │ Student │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 多继承:一个子类可以有多个直接父类 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Student Employee │ │
│ │ ↖ ↗ │ │
│ │ StudentWorker │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 继承的好处: │
│ • 代码复用:子类自动继承父类的属性和方法 │
│ • 模型自然:反映现实世界的分类关系 │
│ • 易于扩展:可以在子类中添加特有的属性和方法 │
│ │
└─────────────────────────────────────────────────────────────────┘
6.2.4 封装(Encapsulation)
| 封装类型 | 说明 | 好处 |
|---|---|---|
| 数据封装 | 属性对外隐藏,通过方法访问 | 数据安全,隐藏实现细节 |
| 方法封装 | 只暴露必要的接口 | 降低耦合,便于修改 |
| 访问控制 | public/private/protected | 精细控制访问权限 |
6.2.5 多态(Polymorphism)
多态的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 多态 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 定义:同一操作在不同对象上可以有不同的行为 │
│ │
│ 方法重载(Overloading):同一类中同名方法,参数不同 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ class Calculator { │ │
│ │ add(int a, int b) { ... } │ │
│ │ add(double a, double b) { ... } │ │
│ │ add(int a, int b, int c) { ... } │ │
│ │ } │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 方法覆盖(Overriding):子类重新定义父类的方法 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ class Shape { draw() { ... } } │ │
│ │ class Circle extends Shape { draw() { 画圆 } } │ │
│ │ class Square extends Shape { draw() { 画方 } } │ │
│ │ │ │
│ │ Shape[] shapes = {circle, square}; │ │
│ │ for(Shape s : shapes) s.draw(); // 多态调用 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
6.3 面向对象数据模型的特点
OODM的关键特点:
┌─────────────────────────────────────────────────────────────────┐
│ 特点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 复杂对象支持 │
│ • 支持嵌套对象和集合类型 │
│ • 可以定义任意复杂的数据结构 │
│ • 例如:对象包含对象列表 │
│ │
│ 2. 对象标识 │
│ • 每个对象有唯一的OID │
│ • OID独立于对象的属性值 │
│ • 支持对象间的引用关系 │
│ │
│ 3. 类型继承 │
│ • 支持类层次结构 │
│ • 子类继承父类的属性和方法 │
│ • 支持类型特化和泛化 │
│ │
│ 4. 方法与行为 │
│ • 数据和操作封装在一起 │
│ • 支持复杂的业务逻辑 │
│ • 方法可以被重载和覆盖 │
│ │
└─────────────────────────────────────────────────────────────────┘
6.4 面向对象数据模型的优缺点
优点
OODM的优势:
┌─────────────────────────────────────────────────────────────────┐
│ 优 点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 适合复杂应用 │
│ • CAD/CAM、GIS、多媒体等领域 │
│ • 需要复杂数据结构的应用 │
│ │
│ 2. 支持复杂数据类型 │
│ • 嵌套对象、集合、数组 │
│ • 用户自定义类型 │
│ • 多媒体数据(图像、音频、视频) │
│ │
│ 3. 自然的对象映射 │
│ • 消除阻抗不匹配问题 │
│ • 对象可以直接持久化 │
│ • 与OO编程语言无缝集成 │
│ │
│ 4. 代码复用 │
│ • 继承机制促进复用 │
│ • 封装保护数据完整性 │
│ │
└─────────────────────────────────────────────────────────────────┘
缺点
OODM的局限:
┌─────────────────────────────────────────────────────────────────┐
│ 缺 点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 缺乏标准 │
│ • ODMG标准未被广泛采用 │
│ • 各产品差异大 │
│ • 可移植性差 │
│ │
│ 2. 查询语言复杂 │
│ • OQL不如SQL简洁 │
│ • 学习曲线陡峭 │
│ • 查询优化困难 │
│ │
│ 3. 与关系模型不兼容 │
│ • 难以与现有关系系统集成 │
│ • 数据迁移成本高 │
│ │
│ 4. 市场接受度低 │
│ • 关系数据库生态系统成熟 │
│ • 缺乏商业推动力 │
│ │
└─────────────────────────────────────────────────────────────────┘
6.5 对象关系模型
对象关系模型的概念:
┌─────────────────────────────────────────────────────────────────┐
│ 对象关系模型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 定义:在关系模型基础上扩展面向对象特性的混合模型 │
│ 也称为"对象关系数据库(ORDBMS)" │
│ │
│ 演进关系: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 关系模型 + 面向对象特性 = 对象关系模型 │ │
│ │ ↓ ↓ ↓ │ │
│ │ 表格 复杂类型 增强的表格 │ │
│ │ SQL 继承 扩展的SQL │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ SQL:1999标准引入的特性: │
│ • 用户定义类型(UDT) │
│ • 行类型(ROW TYPE) │
│ • 数组类型(ARRAY) │
│ • 类型继承 │
│ • 方法定义 │
│ │
└─────────────────────────────────────────────────────────────────┘
PostgreSQL中的对象关系特性示例:
sql
-- 创建复合类型
CREATE TYPE address AS (
street VARCHAR(100),
city VARCHAR(50),
zip VARCHAR(10)
);
-- 使用复合类型
CREATE TABLE employees (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
home_address address, -- 复合类型
work_address address
);
-- 继承
CREATE TABLE persons (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
birth_date DATE
);
CREATE TABLE students (
student_id VARCHAR(20),
major VARCHAR(50)
) INHERITS (persons); -- 继承persons表
-- 数组类型
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
prerequisites INTEGER[] -- 数组
);
6.6 面向对象数据库实例
| 数据库 | 类型 | 特点 |
|---|---|---|
| ObjectDB | 纯OODB | Java对象数据库,JPA兼容 |
| db4o | 纯OODB | 嵌入式对象数据库 |
| Versant | 纯OODB | 企业级对象数据库 |
| PostgreSQL | ORDBMS | 支持复杂类型、继承 |
| Oracle | ORDBMS | 支持UDT、对象表 |
第七章 数据模型的演进与对比
本章将回顾数据模型的发展历程,对比四种基本数据模型,介绍现代新型数据模型,并提供数据模型选择指南。
7.1 数据模型的发展历程
数据模型发展的四个时代:
┌─────────────────────────────────────────────────────────────────┐
│ 发展历程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1950s-1960s: 文件系统时代 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 数据存储在文件中 │ │
│ │ • 程序与数据紧密耦合 │ │
│ │ • 数据冗余严重,维护困难 │ │
│ │ • 代表:COBOL文件处理 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 1960s-1970s: 层次/网状模型时代 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 第一代数据库系统 │ │
│ │ • 导航式数据访问 │ │
│ │ • 代表:IBM IMS(层次)、IDMS(网状) │ │
│ │ • 主要应用于大型主机 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 1970s-至今: 关系模型时代 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • E.F. Codd 1970年提出 │ │
│ │ • 声明式查询(SQL) │ │
│ │ • 数据独立性高 │ │
│ │ • 代表:Oracle、MySQL、PostgreSQL │ │
│ │ • 成为主流数据库模型 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 1990s-至今: 面向对象/对象关系时代 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 解决关系模型的阻抗不匹配问题 │ │
│ │ • 支持复杂数据类型 │ │
│ │ • 纯OODB未成主流,ORDBMS部分成功 │ │
│ │ • SQL:1999引入对象特性 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 2000s-至今: 新型数据模型时代(NoSQL、NewSQL) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 应对大数据、分布式、高并发需求 │ │
│ │ • 文档、键值、列族、图等多种模型 │ │
│ │ • 牺牲部分一致性换取扩展性 │ │
│ │ • 代表:MongoDB、Redis、Neo4j、Cassandra │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
7.2 四种基本数据模型对比
7.2.1 数据结构对比
四种模型的数据结构对比:
┌─────────────────────────────────────────────────────────────────┐
│ 数据结构对比 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 层次模型(树形结构): │
│ 根节点 │
│ / \ │
│ 子节点 子节点 │
│ / \ │
│ 孙节点 孙节点 │
│ │
│ 网状模型(图形结构): │
│ 节点 ──────── 节点 │
│ ↑ ╲ ╱ ↑ │
│ │ ╲ ╱ │ │
│ ↓ ╲╱ ↓ │
│ 节点 ──────── 节点 │
│ │
│ 关系模型(表格结构): │
│ ┌──────┬──────┬──────┐ │
│ │ 列1 │ 列2 │ 列3 │ │
│ ├──────┼──────┼──────┤ │
│ │ 数据 │ 数据 │ 数据 │ ← 行(元组) │
│ └──────┴──────┴──────┘ │
│ │
│ 面向对象模型(对象结构): │
│ ┌──────────────────┐ │
│ │ 对象 │ │
│ │ ├─ 属性(数据) │ │
│ │ └─ 方法(行为) │ │
│ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
7.2.2 数据操作对比
| 模型 | 操作方式 | 特点 | 典型操作 |
|---|---|---|---|
| 层次模型 | 导航式 | 从根开始逐级访问 | GET UNIQUE, GET NEXT |
| 网状模型 | 导航式 | 沿关系链遍历 | FIND, GET, STORE |
| 关系模型 | 集合式(声明式) | SQL描述"要什么" | SELECT, INSERT, UPDATE |
| 面向对象 | 方法调用 | 对象响应消息 | object.method() |
7.2.3 数据独立性对比
数据独立性对比:
┌──────────────────┬────────────┬────────────┬────────────────────┐
│ 模型 │ 物理独立性 │ 逻辑独立性 │ 说明 │
├──────────────────┼────────────┼────────────┼────────────────────┤
│ 层次模型 │ 低 │ 低 │ 结构变化影响程序 │
├──────────────────┼────────────┼────────────┼────────────────────┤
│ 网状模型 │ 低 │ 低 │ 指针依赖性强 │
├──────────────────┼────────────┼────────────┼────────────────────┤
│ 关系模型 │ 高 │ 高 │ 三级模式架构 │
├──────────────────┼────────────┼────────────┼────────────────────┤
│ 面向对象模型 │ 中 │ 中 │ 封装提供部分独立性 │
└──────────────────┴────────────┴────────────┴────────────────────┘
7.2.4 适用场景对比
各模型的最佳应用场景:
┌─────────────────────────────────────────────────────────────────┐
│ 适用场景 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 层次模型: │
│ • 具有明确层次关系的数据(组织架构、文件系统) │
│ • 主要是查询操作,更新较少 │
│ • 历史遗留系统 │
│ │
│ 网状模型: │
│ • 具有复杂多对多关系的数据 │
│ • 制造业、通信等领域的遗留系统 │
│ │
│ 关系模型: │
│ • 结构化数据,事务性应用(最广泛) │
│ • 需要复杂查询和报表 │
│ • OLTP和OLAP系统 │
│ • 需要强一致性的系统 │
│ │
│ 面向对象模型: │
│ • 复杂对象(CAD/CAM、GIS、多媒体) │
│ • 与OOP语言深度集成 │
│ • 需要复杂行为的应用 │
│ │
└─────────────────────────────────────────────────────────────────┘
选择数据模型的考量因素:
| 因素 | 考量内容 |
|---|---|
| 数据结构 | 层次型、网状型、表格型、对象型 |
| 操作复杂度 | 简单CRUD vs 复杂查询 |
| 一致性要求 | 强一致性 vs 最终一致性 |
| 扩展性需求 | 垂直扩展 vs 水平扩展 |
| 开发效率 | 与编程语言的匹配度 |
| 生态系统 | 工具、社区、支持 |
7.3 现代数据模型趋势
现代数据模型分类:
┌─────────────────────────────────────────────────────────────────┐
│ 现代数据模型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 文档模型(Document) │
│ 代表:MongoDB、CouchDB │
│ 特点:JSON/BSON文档,灵活schema,嵌套结构 │
│ 场景:内容管理、用户配置、移动应用 │
│ │
│ 2. 键值模型(Key-Value) │
│ 代表:Redis、Memcached、DynamoDB │
│ 特点:简单高效,极高性能,内存优先 │
│ 场景:缓存、会话管理、实时应用 │
│ │
│ 3. 列族模型(Column-Family) │
│ 代表:HBase、Cassandra、BigTable │
│ 特点:列优先存储,适合大规模分析 │
│ 场景:时序数据、日志分析、大数据处理 │
│ │
│ 4. 图模型(Graph) │
│ 代表:Neo4j、JanusGraph、Amazon Neptune │
│ 特点:节点和边,高效遍历关系 │
│ 场景:社交网络、推荐系统、知识图谱 │
│ │
│ 5. 时序模型(Time-Series) │
│ 代表:InfluxDB、TimescaleDB、OpenTSDB │
│ 特点:时间戳索引,高效写入,聚合查询 │
│ 场景:IoT监控、金融数据、运维指标 │
│ │
│ 6. 多模型数据库(Multi-Model) │
│ 代表:ArangoDB、OrientDB、CosmosDB │
│ 特点:支持多种数据模型,统一API │
│ 场景:需要多种数据类型的复杂应用 │
│ │
└─────────────────────────────────────────────────────────────────┘
7.4 数据模型选择指南
数据模型选择决策流程:
┌─────────────────────────────────────────────────────────────────┐
│ 选择指南 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 步骤1: 需求分析 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 业务需求是什么? │ │
│ │ • 数据量有多大?增长速度如何? │ │
│ │ • 并发访问量是多少? │ │
│ │ • 读写比例如何? │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 步骤2: 数据特征分析 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 数据是结构化/半结构化/非结构化? │ │
│ │ • 数据关系是什么类型?(1:1, 1:N, M:N) │ │
│ │ • 是否需要事务支持? │ │
│ │ • 数据生命周期如何? │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 步骤3: 查询模式分析 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 主要是点查询还是范围查询? │ │
│ │ • 需要复杂的连接操作吗? │ │
│ │ • 需要全文搜索吗? │ │
│ │ • 查询的延迟要求是多少? │ │
│ └─────────────────────────────────────────────────────────┘ │
│ ↓ │
│ 步骤4: 非功能需求分析 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 可扩展性要求(水平/垂直) │ │
│ │ • 一致性要求(强一致/最终一致) │ │
│ │ • 可用性要求(99.9%? 99.99%?) │ │
│ │ • 成本预算如何? │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
决策矩阵:
| 场景 | 推荐模型 | 代表产品 |
|---|---|---|
| 传统事务型应用 | 关系模型 | MySQL, PostgreSQL |
| 内容管理系统 | 文档模型 | MongoDB |
| 高速缓存 | 键值模型 | Redis |
| 社交关系分析 | 图模型 | Neo4j |
| IoT时序数据 | 时序模型 | InfluxDB |
| 大规模日志分析 | 列族模型 | Cassandra |
| 复杂CAD应用 | 对象关系模型 | PostgreSQL |
第八章 实践应用与案例分析
本章通过具体案例演示如何在实际项目中进行数据模型设计,包括电商系统、社交网络、物联网等典型场景。
8.1 案例一:电商系统数据模型设计
需求分析
电商系统核心需求:
┌─────────────────────────────────────────────────────────────────┐
│ 需求分析 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 核心业务: │
│ • 用户管理:注册、登录、个人信息 │
│ • 商品管理:商品信息、分类、库存 │
│ • 订单管理:下单、支付、物流追踪 │
│ • 购物车:添加商品、修改数量、结算 │
│ │
│ 数据特征: │
│ • 强一致性要求(订单、库存) │
│ • 高并发读取(商品浏览) │
│ • 复杂关联查询(订单详情) │
│ • 事务支持必须 │
│ │
│ 推荐模型:关系模型 │
│ │
└─────────────────────────────────────────────────────────────────┘
E-R模型设计
电商系统E-R图:
┌─────────────────────────────────────────────────────────────────┐
│ E-R模型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 用户 │ │ 订单 │ │ 订单明细 │ │
│ │ (User) │─1:N─→│ (Order) │─1:N─→│(OrderItem)│ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │ │ │
│ │ 1:N │ N:1 │
│ ↓ ↓ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 收货地址 │ │ 商品 │ │
│ │(Address) │ │(Product) │ │
│ └──────────┘ └──────────┘ │
│ │ │
│ │ N:1 │
│ ↓ │
│ ┌──────────┐ │
│ │ 分类 │ │
│ │(Category)│ │
│ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
关系模型转换
sql
-- 用户表
CREATE TABLE users (
user_id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
email VARCHAR(100) UNIQUE,
phone VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 商品分类表
CREATE TABLE categories (
category_id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
parent_id INT REFERENCES categories(category_id),
level INT DEFAULT 1
);
-- 商品表
CREATE TABLE products (
product_id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(200) NOT NULL,
description TEXT,
price DECIMAL(10,2) NOT NULL,
stock INT DEFAULT 0,
category_id INT REFERENCES categories(category_id),
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 订单表
CREATE TABLE orders (
order_id BIGINT PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT REFERENCES users(user_id),
total_amount DECIMAL(12,2) NOT NULL,
status ENUM('pending', 'paid', 'shipped', 'completed', 'cancelled'),
shipping_address TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 订单明细表
CREATE TABLE order_items (
item_id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_id BIGINT REFERENCES orders(order_id),
product_id BIGINT REFERENCES products(product_id),
quantity INT NOT NULL,
unit_price DECIMAL(10,2) NOT NULL,
UNIQUE KEY (order_id, product_id)
);
-- 创建索引优化查询
CREATE INDEX idx_orders_user ON orders(user_id);
CREATE INDEX idx_products_category ON products(category_id);
CREATE INDEX idx_order_items_order ON order_items(order_id);
8.2 案例二:社交网络数据模型设计
需求分析
社交网络核心需求:
┌─────────────────────────────────────────────────────────────────┐
│ 需求分析 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 核心业务: │
│ • 用户关系:关注、粉丝、好友 │
│ • 内容发布:帖子、评论、点赞 │
│ • 推荐匹配:二度人脉、共同好友 │
│ • 消息传递:私信、群聊 │
│ │
│ 数据特征: │
│ • 复杂多对多关系(用户关系) │
│ • 需要高效遍历关系链 │
│ • 读多写少 │
│ • 扩展性要求高 │
│ │
└─────────────────────────────────────────────────────────────────┘
关系模型 vs 图模型
| 对比项 | 关系模型 | 图模型 |
|---|---|---|
| 好友查询 | 简单JOIN | 直接遍历边 |
| 二度人脉 | 复杂多JOIN | 2步遍历 |
| N度关系 | 几乎不可行 | N步遍历 |
| 共同好友 | 复杂子查询 | 模式匹配 |
| 推荐算法 | 困难 | 原生支持 |
结论:社交关系适合图模型,用户属性适合关系模型
模型选择与设计
混合模型设计:
┌─────────────────────────────────────────────────────────────────┐
│ 混合架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 关系数据库(MySQL)存储: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 用户基本信息(profiles) │ │
│ │ • 帖子内容(posts) │ │
│ │ • 评论(comments) │ │
│ │ • 消息(messages) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ + │
│ 图数据库(Neo4j)存储: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ • 用户关系(FOLLOWS, FRIENDS) │ │
│ │ • 互动关系(LIKES, SHARES) │ │
│ │ • 用于关系查询和推荐 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Neo4j查询示例:
cypher
// 查询用户的关注者
MATCH (user:User {id: 'U001'})<-[:FOLLOWS]-(follower)
RETURN follower
// 查询二度人脉(朋友的朋友)
MATCH (user:User {id: 'U001'})-[:FRIENDS]->(friend)-[:FRIENDS]->(fof)
WHERE fof <> user AND NOT (user)-[:FRIENDS]->(fof)
RETURN DISTINCT fof
// 查询共同好友
MATCH (u1:User {id: 'U001'})-[:FRIENDS]->(friend)<-[:FRIENDS]-(u2:User {id: 'U002'})
RETURN friend
// 推荐可能认识的人
MATCH (user:User {id: 'U001'})-[:FRIENDS]->(friend)-[:FRIENDS]->(fof)
WHERE NOT (user)-[:FRIENDS]->(fof) AND user <> fof
RETURN fof, COUNT(friend) AS mutual_friends
ORDER BY mutual_friends DESC
LIMIT 10
8.3 案例三:物联网数据模型设计
需求分析
物联网系统核心需求:
┌─────────────────────────────────────────────────────────────────┐
│ 需求分析 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 核心业务: │
│ • 设备管理:设备注册、状态监控 │
│ • 数据采集:传感器数据接收、存储 │
│ • 实时分析:异常检测、告警 │
│ • 历史分析:趋势分析、报表 │
│ │
│ 数据特征: │
│ • 高频写入(每秒百万条) │
│ • 时间序列数据 │
│ • 主要是追加写入,很少更新 │
│ • 需要时间范围查询和聚合 │
│ │
│ 推荐模型:时序模型 │
│ │
└─────────────────────────────────────────────────────────────────┘
模型设计
时序数据库设计(InfluxDB):
┌─────────────────────────────────────────────────────────────────┐
│ 数据模型 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Measurement(类似表):sensor_data │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Tag(索引字段,用于过滤): │ │
│ │ - device_id: 设备ID │ │
│ │ - location: 位置 │ │
│ │ - sensor_type: 传感器类型 │ │
│ │ │ │
│ │ Field(数据字段): │ │
│ │ - temperature: 温度值 │ │
│ │ - humidity: 湿度值 │ │
│ │ - pressure: 气压值 │ │
│ │ │ │
│ │ Timestamp:时间戳(纳秒精度) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 存储优化: │
│ • 自动数据压缩 │
│ • 数据保留策略(如:保留30天详细数据,1年聚合数据) │
│ • 连续查询(自动聚合) │
│ │
└─────────────────────────────────────────────────────────────────┘
InfluxDB查询示例:
sql
-- 插入数据
INSERT sensor_data,device_id=D001,location=Beijing temperature=25.3,humidity=65.2
-- 查询最近1小时的温度数据
SELECT mean(temperature)
FROM sensor_data
WHERE device_id = 'D001' AND time > now() - 1h
GROUP BY time(5m)
-- 查询异常值(温度超过阈值)
SELECT * FROM sensor_data
WHERE temperature > 50 AND time > now() - 24h
-- 按位置统计平均温度
SELECT mean(temperature)
FROM sensor_data
WHERE time > now() - 1d
GROUP BY location
8.4 数据模型设计最佳实践
数据模型设计原则:
┌─────────────────────────────────────────────────────────────────┐
│ 最佳实践 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 需求驱动设计 │
│ • 先理解业务需求,再选择数据模型 │
│ • 识别核心实体和关系 │
│ • 分析查询模式和性能要求 │
│ │
│ 2. 规范化与反规范化平衡 │
│ • OLTP系统:倾向规范化(3NF) │
│ • OLAP系统:适度反规范化 │
│ • 根据实际查询需求调整 │
│ │
│ 3. 可扩展性设计 │
│ • 预留扩展字段或使用JSON列 │
│ • 考虑分库分表策略 │
│ • 设计合理的分片键 │
│ │
│ 4. 性能优化考量 │
│ • 合理设计索引 │
│ • 避免过度索引 │
│ • 考虑读写分离 │
│ • 使用缓存层(Redis) │
│ │
│ 5. 多模型架构考虑 │
│ • 不同类型数据使用不同模型 │
│ • 结构化数据 → 关系模型 │
│ • 关系数据 → 图模型 │
│ • 时序数据 → 时序模型 │
│ • 缓存数据 → 键值模型 │
│ │
└─────────────────────────────────────────────────────────────────┘
| 设计阶段 | 关键活动 | 注意事项 |
|---|---|---|
| 需求分析 | 识别实体、关系、约束 | 与业务方充分沟通 |
| 概念设计 | 绘制E-R图 | 保持简洁清晰 |
| 逻辑设计 | 转换为具体模型 | 选择合适的范式级别 |
| 物理设计 | 创建表、索引 | 考虑硬件和查询特点 |
| 优化调整 | 性能测试、调优 | 基于实际数据和负载 |
第九章 面试与考试重点
本章汇总数据库数据模型相关的面试和考试常见问题,帮助读者巩固核心知识点。
9.1 概念辨析题
核心概念辨析:
┌─────────────────────────────────────────────────────────────────┐
│ 概念辨析 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 数据模型 vs 数据库模式 │
│ • 数据模型:描述数据的抽象方法(如关系模型) │
│ • 数据库模式:数据库的结构定义(如具体表结构) │
│ │
│ 2. 实体 vs 关系 vs 属性 │
│ • 实体:独立存在的事物(如学生、课程) │
│ • 关系:实体之间的联系(如选修) │
│ • 属性:实体或关系的特征(如姓名、成绩) │
│ │
│ 3. 主键 vs 外键 vs 候选键 │
│ • 主键:唯一标识元组的属性(不能为空) │
│ • 外键:引用其他表主键的属性 │
│ • 候选键:可以作为主键的最小超键 │
│ │
│ 4. 概念模型 vs 逻辑模型 vs 物理模型 │
│ • 概念模型:E-R模型,独立于DBMS │
│ • 逻辑模型:关系/网状/层次模型 │
│ • 物理模型:存储结构、索引等 │
│ │
└─────────────────────────────────────────────────────────────────┘
| 概念 | 层次模型 | 网状模型 | 关系模型 | 面向对象模型 |
|---|---|---|---|---|
| 数据结构 | 树 | 图 | 表 | 对象 |
| 访问方式 | 导航式 | 导航式 | 集合式 | 方法调用 |
| 数据独立性 | 低 | 低 | 高 | 中 |
| 理论基础 | 无 | 无 | 集合论 | OOP |
| 代表产品 | IMS | IDMS | MySQL | ObjectDB |
9.2 设计分析题
E-R图绘制技巧
E-R图绘制步骤:
┌─────────────────────────────────────────────────────────────────┐
│ 绘制步骤 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 步骤1:识别实体 │
│ • 找出需要存储信息的独立对象 │
│ • 例如:学生、课程、教师、院系 │
│ │
│ 步骤2:识别属性 │
│ • 确定每个实体的特征 │
│ • 标注主键属性(下划线) │
│ │
│ 步骤3:识别联系 │
│ • 分析实体之间的关系 │
│ • 确定联系的类型(1:1, 1:N, M:N) │
│ │
│ 步骤4:确定联系属性 │
│ • 某些联系可能有自己的属性 │
│ • 例如:选修联系有"成绩"属性 │
│ │
└─────────────────────────────────────────────────────────────────┘
E-R模型到关系模型转换规则
| 转换对象 | 转换规则 |
|---|---|
| 实体 | 转换为一个关系(表),属性成为列,主键保留 |
| 1:1联系 | 合并到任一实体表,或独立成表 |
| 1:N联系 | 外键加到N端实体表 |
| M:N联系 | 独立成一个关联表,包含两端主键 |
| 联系属性 | 加入联系对应的表中 |
范式分析示例
范式判断示例:
问题:判断以下关系的范式级别
Student(学号, 姓名, 系名, 系主任, 课程号, 成绩)
分析:
┌─────────────────────────────────────────────────────────────────┐
│ 函数依赖: │
│ • 学号 → 姓名, 系名 │
│ • 系名 → 系主任 (传递依赖) │
│ • (学号, 课程号) → 成绩 │
│ │
│ 范式判断: │
│ • 1NF ✓ - 所有属性都是原子的 │
│ • 2NF ✗ - 存在部分依赖:姓名、系名只依赖于学号 │
│ │
│ 结论:该关系仅满足1NF │
│ │
│ 规范化: │
│ Student(学号, 姓名, 系名) │
│ Department(系名, 系主任) │
│ Score(学号, 课程号, 成绩) │
└─────────────────────────────────────────────────────────────────┘
9.3 常见面试问题
Q1:什么是数据模型?数据模型的三要素是什么?
答案要点:
• 数据模型是数据库中用于描述数据结构、数据操作和数据约束的抽象工具
• 三要素:
1. 数据结构:描述数据的静态特性,如何组织数据
2. 数据操作:描述可以对数据进行的操作(增删改查)
3. 数据约束:描述数据的完整性规则
Q2:E-R模型的三要素是什么?请举例说明。
答案要点:
• 实体(Entity):客观存在可区分的事物,如"学生"
• 属性(Attribute):实体的特征,如"学号、姓名"
• 联系(Relationship):实体间的关联,如"选修"
• 联系的类型:1:1, 1:N, M:N
Q3:关系模型的优势是什么?为什么它成为主流?
答案要点:
• 结构简单:二维表易于理解和使用
• 数据独立性高:物理和逻辑独立性
• 坚实的数学基础:基于集合论和谓词逻辑
• SQL标准化:统一的查询语言,可移植性好
• 丰富的生态系统:工具、人才、社区
Q4:层次模型和网状模型有什么区别?
答案要点:
• 结构区别:层次是树,网状是图
• 父节点:层次模型只有一个父节点,网状可以有多个
• 关系类型:层次只支持1:N,网状支持M:N
• 灵活性:网状更灵活,但也更复杂
Q5:什么是外键?外键有什么作用?
答案要点:
• 定义:一个表中的属性,引用另一个表的主键
• 作用:
1. 建立表之间的关联关系
2. 维护参照完整性
3. 防止孤立数据(悬挂引用)
• 约束选项:RESTRICT, CASCADE, SET NULL
9.4 真题解析
软考真题示例
题目1:将E-R图转换为关系模式
题目:设有如下实体和联系:
- 学生(学号,姓名,年龄)
- 课程(课程号,课程名,学分)
- 学生与课程之间存在"选修"联系(M:N),联系属性为成绩
请将上述E-R模型转换为关系模式。
答案:
1. 学生(学号, 姓名, 年龄) -- 学号为主键
2. 课程(课程号, 课程名, 学分) -- 课程号为主键
3. 选修(学号, 课程号, 成绩) -- (学号, 课程号)为主键
-- 学号外键引用学生
-- 课程号外键引用课程
题目2:范式判断与分解
题目:关系模式R(A, B, C, D),函数依赖F={A→B, B→C, A→D}
1. 判断R属于第几范式
2. 如果不满足3NF,将其分解为3NF
答案:
1. 候选键:A
• 1NF ✓
• 2NF ✓(无部分依赖,A是单属性)
• 3NF ✗(B→C是传递依赖,B不是候选键)
结论:R ∈ 2NF
2. 分解为3NF:
R1(A, B, D) -- A→B, A→D
R2(B, C) -- B→C
题目3:关系代数表达式
题目:设有关系Student(Sno, Sname, Sage)和SC(Sno, Cno, Grade)
用关系代数表达:查询选修了"C001"课程的学生姓名
答案:
π_Sname(σ_Cno='C001'(Student ⋈ SC))
解释:
1. Student ⋈ SC:连接两个关系
2. σ_Cno='C001':选择课程号为C001的元组
3. π_Sname:投影出学生姓名
总结
数据模型核心要点回顾
核心要点:
┌─────────────────────────────────────────────────────────────────┐
│ 核心要点 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. 数据模型三要素 │
│ • 数据结构:如何组织数据 │
│ • 数据操作:可进行的操作 │
│ • 数据约束:完整性规则 │
│ │
│ 2. 模型层次 │
│ • 概念模型:E-R模型,面向用户 │
│ • 逻辑模型:关系/层次/网状,面向程序员 │
│ • 物理模型:存储结构,面向DBMS │
│ │
│ 3. E-R模型要素 │
│ • 实体(Entity):矩形表示 │
│ • 属性(Attribute):椭圆表示 │
│ • 联系(Relationship):菱形表示 │
│ │
│ 4. 四种基本模型特点 │
│ • 层次模型:树形,1:N,导航访问 │
│ • 网状模型:图形,M:N,导航访问 │
│ • 关系模型:表格,集合操作,SQL │
│ • 面向对象:对象,方法调用,封装继承 │
│ │
└────────────────────────────────────────────