数据库(二):数据模型

数据库数据模型详解

从概念模型到基本数据模型的完整解析


目录

  • 前言
  • [第一章 数据模型概述](#第一章 数据模型概述)
  • [第二章 概念数据模型(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                             │
│     • 面向对象:对象,方法调用,封装继承                        │
│                                                                 │
└────────────────────────────────────────────
相关推荐
曹牧2 小时前
Java:将字符串转换为整数
java·数据库
hcnaisd22 小时前
机器学习模型部署:将模型转化为Web API
jvm·数据库·python
J_liaty2 小时前
SpringBoot整合Canal实现数据库实时同步
数据库·spring boot·后端·canal
草莓熊Lotso2 小时前
从零手搓实现 Linux 简易 Shell:内建命令 + 环境变量 + 程序替换全解析
linux·运维·服务器·数据库·c++·人工智能
Mr_Xuhhh4 小时前
MySQL核心知识梳理:从连接到查询的完整指南
数据库·sql·mysql
wsxlgg4 小时前
MySQL中count(*)、count(1)、count(字段)的区别
数据库·mysql
pengdott10 小时前
Oracle RAC内存融合技术深度解析:集群性能的幕后引擎
数据库·oracle
csudata11 小时前
绿色便携版PostgreSQL发行版重磅发布
数据库·postgresql
阳光九叶草LXGZXJ11 小时前
达梦数据库-学习-48-DmDrs控制台命令(同步之Manager、CPT模块)
linux·运维·数据库·sql·学习