数据库核心概念详解
一、学习资源推荐
1.1 在线学习平台
1. 慕课网
- 网址:https://www.imooc.com/
- 搜索关键词:数据库、MySQL、SQL
- 特点:免费和付费课程丰富
2. 菜鸟教程
- 网址:https://www.runoob.com/sql/
- 内容:SQL 查询、更新、插入、删除
- 特点:免费、系统、适合入门
3. MySQL 官方教程
- 网址:https://dev.mysql.com/doc/
- 内容:官方文档、详细全面
- 特点:权威、深入
1.2 学习重点
code
SQL 学习重点:
│
├── 数据查询(SELECT)
│ ├── 基础查询
│ ├── 条件查询(WHERE)
│ ├── 排序(ORDER BY)
│ ├── 分组(GROUP BY)
│ └── 关联查询(JOIN)
│
├── 数据操作(DML)
│ ├── 插入(INSERT)
│ ├── 更新(UPDATE)
│ └── 删除(DELETE)
│
└── 数据定义(DDL)
├── 创建表(CREATE TABLE)
├── 修改表(ALTER TABLE)
└── 删除表(DROP TABLE)二、表(Table)的概念
2.1 什么是表?
定义:数据库中存储数据的结构,类似于电子表格(Excel)
类比理解:
- 数据库表 ≈ Excel 工作表
- 表头 ≈ 列名(字段名)
- 一行数据 ≈ 一条记录
示例:用户表
code
┌────┬──────────┬────────┬────────┐
│ ID │ username │ name │ gender │
├────┼──────────┼────────┼────────┤
│ 1 │ zhangsan │ 张三 │ 1 │
│ 2 │ lisi │ 李四 │ 2 │
│ 3 │ wangwu │ 王五 │ 1 │
└────┴──────────┴────────┴────────┘
表头(列名):ID、username、name、gender
记录(行):3 条记录2.2 表的组成要素
code
表的组成要素:
│
├── 表名(Table Name)
│ └── 标识表的名称,如:users、orders
│
├── 列/字段(Column/Field)
│ └── 表头,定义数据的类型和含义
│
├── 行/记录(Row/Record)
│ └── 一条完整的数据
│
└── 单元格(Cell)
└── 具体的数据值2.3 创建表的 SQL 语句
sql
-- 创建用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) NOT NULL,
name VARCHAR(50),
gender TINYINT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 查看表结构
DESC users;
-- 查看建表语句
SHOW CREATE TABLE users;
-- 删除表
DROP TABLE users;三、列(Column/Field)的概念
3.1 什么是列?
定义:一组相同类型的数据,代表一个特定的含义
特点:
- 数据类型相同
- 含义特定
- 可设置约束条件
示例:
sql
-- username 列
数据类型:VARCHAR(50)
含义:用户名
约束:NOT NULL(不能为空)
-- gender 列
数据类型:TINYINT
含义:性别(1-男,2-女)
约束:DEFAULT 0(默认为 0)3.2 常见数据类型
数值类型:
| 类型 | 大小 | 范围 | 说明 |
|---|---|---|---|
| TINYINT | 1 字节 | -128 ~ 127 | 小整数,状态值 |
| INT | 4 字节 | -21亿 ~ 21亿 | 整数,ID |
| BIGINT | 8 字节 | 非常大 | 大整数,时间戳 |
| DECIMAL | 可变 | 精确小数 | 金额 |
| FLOAT | 4 字节 | 近似小数 | 评分 |
字符串类型:
| 类型 | 说明 | 示例 |
|---|---|---|
| CHAR(n) | 固定长度 | 手机号:CHAR(11) |
| VARCHAR(n) | 可变长度 | 用户名:VARCHAR(50) |
| TEXT | 长文本 | 文章内容 |
日期时间类型:
| 类型 | 格式 | 说明 |
|---|---|---|
| DATE | YYYY-MM-DD | 日期 |
| TIME | HH:MM:SS | 时间 |
| DATETIME | YYYY-MM-DD HH:MM:SS | 日期时间 |
| TIMESTAMP | 时间戳 | 自动更新 |
完整建表示例:
sql
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '商品ID',
name VARCHAR(100) NOT NULL COMMENT '商品名称',
price DECIMAL(10, 2) NOT NULL COMMENT '价格',
stock INT DEFAULT 0 COMMENT '库存',
status TINYINT DEFAULT 1 COMMENT '状态:1-上架,0-下架',
description TEXT COMMENT '商品描述',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';3.3 列的约束条件
sql
CREATE TABLE users (
-- PRIMARY KEY:主键约束
id INT PRIMARY KEY AUTO_INCREMENT,
-- NOT NULL:非空约束
username VARCHAR(50) NOT NULL,
-- UNIQUE:唯一约束
email VARCHAR(100) UNIQUE,
-- DEFAULT:默认值
status TINYINT DEFAULT 1,
-- CHECK:检查约束
age INT CHECK (age >= 0 AND age <= 150),
-- FOREIGN KEY:外键约束
dept_id INT,
FOREIGN KEY (dept_id) REFERENCES departments(id)
);四、记录(Record/Row)的概念
4.1 什么是记录?
定义:一行完整的、相关的数据
特点:
- 包含所有列的值
- 代表一个完整的实体
- 通过主键唯一标识
示例:
sql
-- 一条记录
{
id: 1,
username: 'zhangsan',
name: '张三',
gender: 1,
created_at: '2024-01-01 10:00:00'
}4.2 记录的操作
1. 插入记录(INSERT)
sql
-- 插入单条记录
INSERT INTO users (username, name, gender)
VALUES ('zhangsan', '张三', 1);
-- 插入多条记录
INSERT INTO users (username, name, gender) VALUES
('lisi', '李四', 2),
('wangwu', '王五', 1);2. 查询记录(SELECT)
sql
-- 查询所有记录
SELECT * FROM users;
-- 查询特定字段
SELECT id, username, name FROM users;
-- 条件查询
SELECT * FROM users WHERE gender = 1;
-- 排序
SELECT * FROM users ORDER BY created_at DESC;
-- 分页
SELECT * FROM users LIMIT 0, 10; -- 第 1 页,每页 10 条
SELECT * FROM users LIMIT 10, 10; -- 第 2 页,每页 10 条3. 更新记录(UPDATE)
sql
-- 更新单个字段
UPDATE users SET name = '张三丰' WHERE id = 1;
-- 更新多个字段
UPDATE users
SET name = '张三丰', gender = 1
WHERE id = 1;4. 删除记录(DELETE)
sql
-- 删除特定记录
DELETE FROM users WHERE id = 1;
-- 条件删除
DELETE FROM users WHERE status = 0;五、主键(Primary Key)的概念
5.1 什么是主键?
定义:表中唯一标识每一行记录的字段或字段组合
核心特点:
- 唯一性:每条记录的主键值唯一
- 非空性:主键值不能为 NULL
- 稳定性:主键值不应频繁变化
- 自带索引:主键自动创建索引
类比理解:
- 主键 ≈ 身份证号(唯一标识一个人)
- 主键 ≈ 学号(唯一标识一个学生)
5.2 主键的类型
1. 单列主键
sql
-- 单列主键
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
name VARCHAR(50)
);
-- 或者在表定义后指定
CREATE TABLE users (
id INT AUTO_INCREMENT,
username VARCHAR(50),
name VARCHAR(50),
PRIMARY KEY (id)
);2. 联合主键(复合主键)
sql
-- 联合主键:多个字段组合作为主键
CREATE TABLE student_courses (
student_id INT,
course_id INT,
score DECIMAL(5, 2),
PRIMARY KEY (student_id, course_id) -- 联合主键
);联合主键特点:
- 单个字段可以重复
- 字段组合必须唯一
- 适用于多对多关系的中间表
5.3 主键的作用
code
主键的三大作用:
│
├── 1⃣ 唯一标识
│ └── 通过主键值唯一确定一条记录
│
├── 2⃣ 建立索引
│ └── 主键自动创建索引,提高查询速度
│
└── 3⃣ 关联关系
└── 主键作为外键,建立表之间的关联5.4 主键 vs 唯一键(UNIQUE)
| 对比项 | 主键(PRIMARY KEY) | 唯一键(UNIQUE) |
|---|---|---|
| 唯一性 | 必须 | 必须 |
| 非空性 | 必须 | 允许 NULL |
| 数量 | 每表只能有一个 | 可以有多个 |
| 索引 | 自动创建聚簇索引 | 自动创建非聚簇索引 |
| 用途 | 标识记录 | 防止重复 |
sql
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT, -- 主键
username VARCHAR(50) UNIQUE, -- 唯一键
email VARCHAR(100) UNIQUE, -- 唯一键
phone VARCHAR(20) -- 普通字段
);5.5 主键的最佳实践
code
主键设计原则:
│
├── 推荐做法
│ ├── 使用自增整数(AUTO_INCREMENT)
│ ├── 主键值简短、稳定
│ ├── 不要使用业务字段作为主键
│ └── 不要修改主键值
│
└── 不推荐做法
├── 使用 UUID(太长、索引效率低)
├── 使用业务字段(如手机号、邮箱)
├── 使用联合主键(除非必要)
└── 频繁修改主键值六、外键(Foreign Key)的概念
6.1 什么是外键?
定义:一个表中的字段,引用另一个表的主键,建立两个表之间的关联关系
核心特点:
- 建立表之间的关联
- 保证数据的一致性
- 约束数据的完整性
类比理解:
- 外键 ≈ 学生证上的班级编号(关联到班级表)
6.2 外键的作用
code
外键的作用:
│
├── 1⃣ 建立关联关系
│ └── 连接两个表的数据
│
├── 2⃣ 保证数据一致性
│ └── 不能插入不存在的外键值
│
└── 3⃣ 级联操作
├── 级联删除(ON DELETE CASCADE)
└── 级联更新(ON UPDATE CASCADE)6.3 三种关联关系
6.3.1 一对一关系(1:1)
定义:一个表的记录对应另一个表的一条记录
示例:
- 用户 ↔ 身份证信息
- 学生 ↔ 学籍档案
实现方式:
sql
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
name VARCHAR(50)
);
-- 身份证信息表(一对一)
CREATE TABLE user_id_cards (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT UNIQUE, -- UNIQUE 确保一对一
id_card_no VARCHAR(18),
FOREIGN KEY (user_id) REFERENCES users(id)
);ER 图:
code
┌─────────┐ ┌──────────────┐
│ 用户 │ 1 ──── 1 │ 身份证信息 │
└─────────┘ └──────────────┘6.3.2 一对多关系(1:N)
定义:一个表的记录对应另一个表的多条记录
示例:
- 用户 ↔ 订单(一个用户多个订单)
- 班级 ↔ 学生(一个班级多个学生)
- 用户 ↔ 书本(一个用户多本书)
实现方式:
sql
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
password VARCHAR(255)
);
-- 书本表(一对多)
CREATE TABLE books (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
user_id INT, -- 外键在"多"的一方
FOREIGN KEY (user_id) REFERENCES users(id)
);数据示例:
code
用户表(users):
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | zhangsan | 123456 |
+----+----------+----------+
书本表(books):
+----+----------+---------+
| id | name | user_id |
+----+----------+---------+
| 1 | 语文书 | 1 |
| 2 | 数学书 | 1 |
| 3 | 英语书 | 1 |
+----+----------+---------+
一个用户(张三)对应多本书(语文、数学、英语)ER 图:
code
┌─────────┐ ┌─────────┐
│ 用户 │ 1 ──── N │ 书本 │
└─────────┘ └─────────┘6.3.3 多对多关系(M:N)
定义:一个表的记录对应另一个表的多条记录,反之亦然
示例:
- 用户 ↔ 角色(一个用户多个角色,一个角色多个用户)
- 学生 ↔ 课程(一个学生多门课程,一门课程多个学生)
实现方式:
sql
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50)
);
-- 角色表
CREATE TABLE roles (
id INT PRIMARY KEY AUTO_INCREMENT,
role_name VARCHAR(50)
);
-- 用户角色关联表(多对多)
CREATE TABLE user_roles (
user_id INT,
role_id INT,
PRIMARY KEY (user_id, role_id), -- 联合主键
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (role_id) REFERENCES roles(id)
);数据示例:
code
用户表(users):
+----+----------+
| id | username |
+----+----------+
| 1 | 张三 |
| 2 | 李四 |
+----+----------+
角色表(roles):
+----+------------+
| id | role_name |
+----+------------+
| 1 | 中队长 |
| 2 | 语文科代表 |
+----+------------+
用户角色关联表(user_roles):
+---------+---------+
| user_id | role_id |
+---------+---------+
| 1 | 1 | -- 张三 是 中队长
| 1 | 2 | -- 张三 是 语文科代表
| 2 | 1 | -- 李四 是 中队长
+---------+---------+
一个用户(张三)有多个角色(中队长、语文科代表)
一个角色(中队长)有多个用户(张三、李四)ER 图:
code
┌─────────┐ ┌─────────────┐ ┌─────────┐
│ 用户 │ N ──── M │ 用户角色表 │ M ──── N │ 角色 │
└─────────┘ └─────────────┘ └─────────┘6.4 三种关联关系对比
| 关系类型 | 表示方法 | 外键位置 | 示例 |
|---|---|---|---|
| 一对一 | 1:1 | 任一表(加 UNIQUE) | 用户 ↔ 身份证 |
| 一对多 | 1:N | "多"的一方 | 用户 ↔ 订单 |
| 多对多 | M:N | 中间表 | 用户 ↔ 角色 |
code
三种关系速记:
│
├── 1:1 一对一
│ └── 外键 + UNIQUE
│
├── 1:N 一对多
│ └── 外键在"多"的一方
│
└── M:N 多对多
└── 中间表 + 联合主键七、为什么要分表存储?
7.1 问题场景
假设:将书本信息存入用户表
方案一:数组存储
sql
-- 不推荐:将书本作为数组存储
CREATE TABLE users_bad (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
books TEXT -- 存储 JSON 数组:["语文书","数学书","英语书"]
);问题:
- 数据结构不清晰
- 不方便索引和查询
- 修改困难(需要解析 JSON)
- 关系型数据库不原生支持数组
方案二:冗余字段
sql
-- 不推荐:大量冗余数据
CREATE TABLE users_bad (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
book1 VARCHAR(50), -- 书本1
book2 VARCHAR(50), -- 书本2
book3 VARCHAR(50) -- 书本3
);
-- 数据示例
+----+----------+--------+--------+--------+
| id | username | book1 | book2 | book3 |
+----+----------+--------+--------+--------+
| 1 | 张三 | 语文书 | 数学书 | 英语书 |
+----+----------+--------+--------+--------+问题:
- 冗余数据多
- 扩展性差(书本数量有限)
- 查询复杂
- 数据一致性难维护
7.2 正确方案:分表存储
sql
-- 推荐:分表存储
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50)
);
-- 书本表
CREATE TABLE books (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
user_id INT,
FOREIGN KEY (user_id) REFERENCES users(id)
);优势:
- 数据结构清晰
- 方便索引和查询
- 扩展性强
- 数据一致性有保障
7.3 分表的好处
code
分表存储的优势:
│
├── 1⃣ 避免数据冗余
│ └── 数据只存储一次,减少存储空间
│
├── 2⃣ 提高查询效率
│ └── 可以建立索引,快速查询
│
├── 3⃣ 保证数据一致性
│ └── 修改一处,所有引用自动更新
│
├── 4⃣ 增强扩展性
│ └── 可以无限扩展关联数据
│
└── 5⃣ 易于维护
└── 数据独立,修改互不影响八、索引(Index)的概念
8.1 什么是索引?
定义:数据库中用于提高查询速度的数据结构
类比理解:
- 索引 ≈ 图书馆的目录卡片
- 索引 ≈ 书本的目录
- 索引 ≈ 字典的拼音索引
索引原理:
code
无索引查询:
遍历所有数据 → 逐条比较 → 时间复杂度 O(n)
有索引查询:
查询索引结构 → 快速定位 → 时间复杂度 O(log n)8.2 索引的类型
1. 主键索引(自动创建)
sql
-- 主键自动创建索引
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50)
);2. 唯一索引(UNIQUE)
sql
-- 唯一索引
CREATE UNIQUE INDEX idx_email ON users(email);
-- 或在表定义时
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
email VARCHAR(100) UNIQUE
);3. 普通索引(INDEX)
sql
-- 创建普通索引
CREATE INDEX idx_username ON users(username);
-- 或在表定义时
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
INDEX idx_username (username)
);4. 组合索引
sql
-- 组合索引
CREATE INDEX idx_status_created ON users(status, created_at);
-- 使用原则:最左前缀原则
-- 使用索引:WHERE status = 1
-- 使用索引:WHERE status = 1 AND created_at > '2024-01-01'
-- 不使用索引:WHERE created_at > '2024-01-01'(缺少最左字段)5. 全文索引(FULLTEXT)
sql
-- 全文索引(用于文本搜索)
CREATE FULLTEXT INDEX idx_content ON articles(content);
-- 使用全文搜索
SELECT * FROM articles WHERE MATCH(content) AGAINST('数据库');8.3 索引的优缺点
优点:
- 大幅提高查询速度
- 加速 ORDER BY 和 GROUP BY
- 提高表连接查询效率
缺点:
- 占用存储空间
- 降低写入速度(INSERT、UPDATE、DELETE)
- 需要维护成本
8.4 索引使用原则
code
索引使用原则:
│
├── 应该创建索引的字段
│ ├── 主键(自动创建)
│ ├── 外键(建议创建)
│ ├── 经常查询的字段
│ ├── 经常排序的字段
│ └── 经常作为 WHERE 条件的字段
│
└── 不应该创建索引的字段
├── 数据量小的表
├── 频繁更新的字段
├── 区分度低的字段(如性别、状态)
└── 很少查询的字段8.5 查看和删除索引
sql
-- 查看表的索引
SHOW INDEX FROM users;
-- 删除索引
DROP INDEX idx_username ON users;
-- 或使用 ALTER TABLE
ALTER TABLE users DROP INDEX idx_username;8.6 索引优化示例
sql
-- 场景:查询状态为启用且创建时间在 2024 年的用户
-- 1. 创建组合索引
CREATE INDEX idx_status_created ON users(status, created_at);
-- 2. 查询语句
SELECT * FROM users
WHERE status = 1
AND created_at >= '2024-01-01'
AND created_at < '2025-01-01';
-- 3. 使用 EXPLAIN 分析查询
EXPLAIN SELECT * FROM users WHERE status = 1;
-- 查看是否使用了索引
-- key: idx_status_created(使用了索引)
-- rows: 预估扫描行数九、关联查询(JOIN)
9.1 什么是关联查询?
定义:通过外键关联,同时查询多个表的数据
9.2 关联查询类型
1. INNER JOIN(内连接)
sql
-- 内连接:只返回两个表中都有匹配的记录
SELECT
users.username,
books.name AS book_name
FROM users
INNER JOIN books ON users.id = books.user_id;
-- 结果:只显示有书本的用户2. LEFT JOIN(左连接)
sql
-- 左连接:返回左表所有记录,右表没有则为 NULL
SELECT
users.username,
books.name AS book_name
FROM users
LEFT JOIN books ON users.id = books.user_id;
-- 结果:显示所有用户,没有书本的用户显示 NULL3. RIGHT JOIN(右连接)
sql
-- 右连接:返回右表所有记录,左表没有则为 NULL
SELECT
users.username,
books.name AS book_name
FROM users
RIGHT JOIN books ON users.id = books.user_id;
-- 结果:显示所有书本,没有用户的书本显示 NULL9.3 多表关联查询示例
sql
-- 三表关联:用户 - 角色 - 权限
SELECT
u.username,
r.role_name,
p.permission_name
FROM users u
INNER JOIN user_roles ur ON u.id = ur.user_id
INNER JOIN roles r ON ur.role_id = r.id
INNER JOIN role_permissions rp ON r.id = rp.role_id
INNER JOIN permissions p ON rp.permission_id = p.id
WHERE u.id = 1;9.4 关联查询性能优化
sql
-- 1. 使用索引:确保关联字段有索引
CREATE INDEX idx_user_id ON books(user_id);
-- 2. 只查询需要的字段
SELECT u.username, b.name
FROM users u
INNER JOIN books b ON u.id = b.user_id;
-- 3. 使用表别名
SELECT u.username, b.name
FROM users AS u
INNER JOIN books AS b ON u.id = b.user_id;
-- 4. 避免关联过多表(建议不超过 5 张)十、最佳实践
10.1 表设计原则
code
表设计原则:
│
├── 1⃣ 范式设计
│ ├── 第一范式:字段不可再分
│ ├── 第二范式:非主键字段完全依赖主键
│ └── 第三范式:非主键字段不传递依赖主键
│
├── 2⃣ 命名规范
│ ├── 表名:小写 + 下划线 + 复数(users、orders)
│ ├── 字段名:小写 + 下划线(user_name、created_at)
│ └── 避免使用保留字
│
├── 3⃣ 字段设计
│ ├── 选择合适的数据类型
│ ├── 设置合理的默认值
│ ├── 添加 NOT NULL 约束
│ └── 添加 COMMENT 注释
│
└── 4⃣ 索引设计
├── 主键自动创建索引
├── 外键建议创建索引
├── 经常查询的字段创建索引
└── 避免过多索引10.2 性能优化建议
sql
-- 1. 使用 EXPLAIN 分析查询
EXPLAIN SELECT * FROM users WHERE status = 1;
-- 2. 避免 SELECT *
SELECT id, username, name FROM users;
-- 3. 使用 LIMIT 分页
SELECT * FROM users LIMIT 0, 10;
-- 4. 使用索引覆盖
CREATE INDEX idx_covering ON users(status, created_at, username);
-- 5. 避免在 WHERE 子句中使用函数
-- 不推荐
SELECT * FROM users WHERE YEAR(created_at) = 2024;
-- 推荐
SELECT * FROM users
WHERE created_at >= '2024-01-01'
AND created_at < '2025-01-01';10.3 完整建表示例
sql
-- 用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',
username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',
password VARCHAR(255) NOT NULL COMMENT '密码(加密)',
email VARCHAR(100) UNIQUE COMMENT '邮箱',
phone CHAR(11) COMMENT '手机号',
status TINYINT DEFAULT 1 COMMENT '状态:1-启用,0-禁用',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_username (username),
INDEX idx_email (email),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 订单表
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '订单ID',
order_no VARCHAR(50) NOT NULL UNIQUE COMMENT '订单号',
user_id INT NOT NULL COMMENT '用户ID',
total_amount DECIMAL(10, 2) NOT NULL COMMENT '订单总金额',
status TINYINT DEFAULT 0 COMMENT '状态:0-待支付,1-已支付,2-已发货,3-已完成',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
FOREIGN KEY (user_id) REFERENCES users(id),
INDEX idx_user_id (user_id),
INDEX idx_order_no (order_no),
INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';十一、常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 主键冲突 | 插入重复的主键值 | 使用 AUTO_INCREMENT 自动生成 |
| 外键约束失败 | 外键值不存在于关联表 | 先插入关联表数据,或取消外键约束 |
| 查询速度慢 | 缺少索引或查询复杂 | 添加索引、优化 SQL、使用 EXPLAIN 分析 |
| 数据冗余 | 表设计不合理 | 范式设计、分表存储 |
| 更新异常 | 数据一致性问题 | 使用事务、外键约束 |
| 中文乱码 | 字符集不正确 | 使用 utf8mb4 字符集 |
| 磁盘空间不足 | 数据增长快 | 定期清理、数据归档、扩容 |
| 死锁 | 事务操作顺序不一致 | 统一操作顺序、减少事务时间 |
十二、学习要点总结
12.1 核心要点
- 表:数据库存储数据的结构,类似 Excel 表格
- 列:一组相同类型的数据,代表特定含义
- 记录:一行完整的、相关的数据
- 主键:唯一标识每一行记录的字段,自带索引
- 外键:建立表之间关联关系的字段
- 三种关系:一对一、一对多、多对多
- 索引:提高查询速度的数据结构
- 分表:避免数据冗余,提高性能
12.2 记忆技巧
code
记忆技巧:
│
├── 表 ≈ Excel 工作表
├── 列 ≈ 表头字段
├── 记录 ≈ 一行数据
├── 主键 ≈ 身份证号(唯一标识)
├── 外键 ≈ 关联桥梁
├── 索引 ≈ 图书馆目录
│
└── 三种关系
├── 1:1 → UNIQUE 外键
├── 1:N → 外键在"多"方
└── M:N → 中间表12.3 学习路径
code
学习路径规划:
│
├── 第一阶段:理解概念(1-2 天)
│ ├── 理解表、列、记录
│ ├── 理解主键、外键
│ └── 理解三种关联关系
│
├── 第二阶段:实践练习(1 周)
│ ├── 创建数据库和表
│ ├── 实现 CRUD 操作
│ └── 练习关联查询
│
└── 第三阶段:深入应用(持续)
├── 索引优化
├── 查询优化
└── 数据库设计十三、延伸学习资源
13.1 官方文档
13.2 推荐阅读
- 《MySQL 必知必会》
- 《高性能 MySQL》
- 《数据库系统概念》
13.3 练习建议
- 基础练习:创建表、插入数据、查询数据
- 进阶练习:关联查询、聚合查询、子查询
- 实战练习:设计一个完整的用户-订单系统
- 优化练习:使用 EXPLAIN 分析查询,优化索引
十四、知识图谱
code
数据库核心概念知识图谱:
│
├── 表(Table)
│ ├── 表名
│ ├── 列/字段
│ └── 行/记录
│
├── 列(Column)
│ ├── 数据类型
│ ├── 约束条件
│ └── 默认值
│
├── 主键(Primary Key)
│ ├── 唯一标识
│ ├── 自带索引
│ ├── 单列主键
│ └── 联合主键
│
├── 外键(Foreign Key)
│ ├── 建立关联
│ ├── 保证一致性
│ └── 级联操作
│
├── 三种关联关系
│ ├── 一对一(1:1)
│ ├── 一对多(1:N)
│ └── 多对多(M:N)
│
├── 索引(Index)
│ ├── 主键索引
│ ├── 唯一索引
│ ├── 普通索引
│ └── 组合索引
│
└── 最佳实践
├── 表设计原则
├── 性能优化
└── 查询优化笔记整理时间:2026-03-07
最后更新时间:2026-03-07