当你准备构建一个在线教育平台(比如我们称之为“智慧学堂”)时,首先要解决的问题是什么?没错,就是如何可靠地存储和管理用户、课程、订单等海量数据。这时,一个强大而稳定的数据库系统就显得至关重要,而 MySQL 作为最流行的开源关系型数据库之一,无疑是许多开发者的首选。
本文将以“智慧学堂”为场景,系统性地为你解析 MySQL 的核心概念、SQL语言精髓以及各种数据类型的选用之道,帮助你打下坚实的数据存储基础。
1. MySQL核心概念
1.1 基础概念
专业性描述
MySQL 是一个开源的关系型数据库管理系统(RDBMS),使用结构化查询语言(SQL)进行数据库管理。它采用客户端/服务器架构,支持多用户并发访问,提供事务处理、数据完整性约束、备份恢复等功能。
大白话类比
它就像一个数字化的图书馆:
- 数据库:整个图书馆
- 数据表:图书馆里的书架(每个书架放一类书)
- 记录:书架上的每一本书
- 字段:书的属性(书名、作者、出版社)
- 索引:图书馆的检索系统(帮你快速找到书)
- SQL:图书管理员的操作语言(查书、上书、下架)
关键概念详解
| 概念 |
定义 |
智慧学堂示例 |
作用 |
| 数据库 |
存储相关数据的集合 |
smart_classroom数据库 |
存储所有在线教育相关数据 |
| 表 |
数据库中的二维数据结构 |
users表、courses表 |
存储特定类型的数据 |
| 字段/列 |
表中的数据属性 |
username、email、price |
定义数据的结构和类型 |
| 记录/行 |
表中的一行数据 |
一个用户信息、一门课程信息 |
存储具体的数据实例 |
| 主键 |
唯一标识表中每条记录的字段 |
users表的id字段 |
确保数据唯一性,建立关联 |
| 外键 |
关联其他表主键的字段 |
orders表的user_id关联users表id |
建立表间关系,保证数据完整性 |
| 索引 |
提高查询速度的数据结构 |
在email字段建立索引 |
加速数据检索 |
1.2 SQL类型
专业性描述
SQL(Structured Query Language)是用于管理关系数据库的标准语言。根据功能不同,SQL语句主要分为四类:数据定义语言(DDL)、数据操作语言(DML)、数据查询语言(DQL)、数据控制语言(DCL)。
SQL语句分类与示例
| SQL类型 |
功能 |
主要命令 |
智慧学堂示例 |
| DDL(数据定义语言) |
定义和管理数据库结构 |
CREATE, ALTER, DROP, TRUNCATE |
创建表、修改表结构、删除表 |
| DML(数据操作语言) |
操作数据库中的数据 |
INSERT, UPDATE, DELETE |
添加用户、更新课程、删除订单 |
| DQL(数据查询语言) |
查询数据库中的数据 |
SELECT |
查询用户列表、搜索课程、统计订单 |
| DCL(数据控制语言) |
控制数据库访问权限 |
GRANT, REVOKE |
授权用户访问、撤销权限 |
DDL示例:创建表
-- 创建用户表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT, -- 用户ID,主键,自增
username VARCHAR(50) NOT NULL UNIQUE, -- 用户名,非空,唯一
email VARCHAR(100) NOT NULL UNIQUE, -- 邮箱,非空,唯一
password_hash VARCHAR(255) NOT NULL, -- 密码哈希
real_name VARCHAR(50), -- 真实姓名
phone VARCHAR(20), -- 手机号
avatar_url VARCHAR(500), -- 头像URL
user_type ENUM('student', 'teacher', 'admin') DEFAULT 'student', -- 用户类型
status ENUM('active', 'inactive', 'banned') DEFAULT 'active', -- 状态
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 更新时间
INDEX idx_email (email), -- 邮箱索引
INDEX idx_username (username), -- 用户名索引
INDEX idx_created_at (created_at) -- 创建时间索引
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 创建课程表
CREATE TABLE courses (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(200) NOT NULL, -- 课程标题
description TEXT, -- 课程描述
teacher_id INT NOT NULL, -- 教师ID
category_id INT, -- 分类ID
price DECIMAL(10, 2) DEFAULT 0.00, -- 价格,10位整数2位小数
discount_price DECIMAL(10, 2), -- 折扣价
cover_image VARCHAR(500), -- 封面图
video_count INT DEFAULT 0, -- 视频数量
total_duration INT DEFAULT 0, -- 总时长(分钟)
average_rating DECIMAL(3, 2) DEFAULT 0.00, -- 平均评分
review_count INT DEFAULT 0, -- 评价数量
student_count INT DEFAULT 0, -- 学生数量
is_recommended BOOLEAN DEFAULT FALSE, -- 是否推荐
is_free BOOLEAN DEFAULT FALSE, -- 是否免费
status ENUM('draft', 'published', 'hidden') DEFAULT 'draft',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (teacher_id) REFERENCES users(id) ON DELETE CASCADE, -- 外键约束
INDEX idx_teacher_id (teacher_id),
INDEX idx_category_id (category_id),
INDEX idx_status (status),
INDEX idx_created_at (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
DML示例:数据操作
-- INSERT:插入数据
-- 插入用户
INSERT INTO users (username, email, password_hash, user_type)
VALUES ('张三', 'zhangsan@example.com', 'hashed_password_123', 'student');
-- 插入课程
INSERT INTO courses (title, description, teacher_id, price, status)
VALUES ('Python入门教程', '从零开始学习Python编程', 1001, 299.00, 'published');
-- UPDATE:更新数据
-- 更新用户信息
UPDATE users
SET phone = '13800138000', updated_at = NOW()
WHERE id = 1001;
-- 更新课程价格
UPDATE courses
SET price = price * 0.8, discount_price = price * 0.8
WHERE id = 2001;
-- DELETE:删除数据
-- 删除无效订单
DELETE FROM orders
WHERE status = 'cancelled' AND created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- 软删除:更新状态而非物理删除
UPDATE users
SET status = 'inactive', updated_at = NOW()
WHERE last_login < DATE_SUB(NOW(), INTERVAL 365 DAY);
DQL示例:数据查询
-- SELECT:查询数据
-- 基本查询
SELECT id, username, email, created_at
FROM users
WHERE user_type = 'student'
ORDER BY created_at DESC
LIMIT 10;
-- 多表连接查询
SELECT
u.username,
c.title AS course_title,
o.amount,
o.created_at AS order_time
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN courses c ON o.course_id = c.id
WHERE o.status = 'paid'
ORDER BY o.created_at DESC
LIMIT 20;
-- 聚合查询
SELECT
DATE(created_at) AS order_date,
COUNT(*) AS order_count,
SUM(amount) AS total_amount,
AVG(amount) AS average_amount
FROM orders
WHERE status = 'paid'
AND created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY DATE(created_at)
ORDER BY order_date DESC;
-- 子查询
SELECT
username,
email,
(SELECT COUNT(*) FROM orders WHERE user_id = u.id AND status = 'paid') AS paid_order_count
FROM users u
WHERE user_type = 'student'
HAVING paid_order_count > 0
ORDER BY paid_order_count DESC;
DCL示例:权限控制
-- GRANT:授予权限
-- 授予只读权限
GRANT SELECT ON smart_classroom.* TO 'readonly_user'@'localhost';
-- 授予特定表权限
GRANT SELECT, INSERT, UPDATE ON smart_classroom.users TO 'app_user'@'%';
-- 授予管理员权限
GRANT ALL PRIVILEGES ON smart_classroom.* TO 'admin_user'@'localhost' WITH GRANT OPTION;
-- REVOKE:撤销权限
-- 撤销插入权限
REVOKE INSERT ON smart_classroom.users FROM 'app_user'@'%';
-- 撤销所有权限
REVOKE ALL PRIVILEGES ON smart_classroom.* FROM 'old_user'@'localhost';
2. MySQL的数据类型
2.1 数值类型
专业性描述
MySQL的数值类型用于存储数字数据,包括整数类型和浮点数类型。整数类型有精确的数值范围,浮点数类型可以存储小数。选择适当的数值类型可以节省存储空间并提高查询性能。
整数类型
| 类型 |
存储空间 |
有符号范围 |
无符号范围 |
智慧学堂应用 |
| TINYINT |
1字节 |
-128 ~ 127 |
0 ~ 255 |
用户状态、课程是否推荐(0/1) |
| SMALLINT |
2字节 |
-32768 ~ 32767 |
0 ~ 65535 |
课程分类ID、地区编码 |
| MEDIUMINT |
3字节 |
-8388608 ~ 8388607 |
0 ~ 16777215 |
中等规模的ID、计数器 |
| INT/INTEGER |
4字节 |
-2147483648 ~ 2147483647 |
0 ~ 4294967295 |
用户ID、课程ID、订单ID(主键) |
| BIGINT |
8字节 |
-2^63 ~ 2^63-1 |
0 ~ 2^64-1 |
分布式ID、极大数量统计 |
浮点数类型
| 类型 |
存储空间 |
精度 |
说明 |
智慧学堂应用 |
| FLOAT |
4字节 |
单精度浮点 |
约7位有效数字 |
学习进度百分比、简单计算 |
| DOUBLE |
8字节 |
双精度浮点 |
约15位有效数字 |
科学计算、复杂统计 |
| DECIMAL(M,D) |
变长 |
精确小数 |
M为总位数,D为小数位 |
课程价格、订单金额(精确计算) |
数值类型使用示例
-- 整数类型示例
CREATE TABLE example_integers (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, -- 主键,无符号
user_status TINYINT DEFAULT 1, -- 状态:1正常,0禁用
course_level TINYINT UNSIGNED, -- 课程等级:1初级,2中级,3高级
view_count INT UNSIGNED DEFAULT 0, -- 浏览次数
like_count INT UNSIGNED DEFAULT 0, -- 点赞数
student_count MEDIUMINT UNSIGNED DEFAULT 0, -- 学生数
order_id BIGINT UNSIGNED, -- 订单ID(可能很大)
region_code SMALLINT UNSIGNED -- 地区编码
);
-- 浮点数类型示例
CREATE TABLE example_decimals (
id INT PRIMARY KEY,
-- 价格相关
original_price DECIMAL(10, 2) NOT NULL, -- 原价,总共10位,2位小数
discount_price DECIMAL(10, 2), -- 折扣价
final_price DECIMAL(10, 2) NOT NULL, -- 最终价
-- 评分相关
average_rating DECIMAL(3, 2) DEFAULT 0.00, -- 平均评分,0.00-5.00
rating_count INT UNSIGNED DEFAULT 0, -- 评分人数
-- 进度相关
completion_rate FLOAT, -- 完成率,如85.5%
accuracy_rate DOUBLE, -- 准确率,需要高精度
-- 统计相关
revenue DECIMAL(15, 2) DEFAULT 0.00 -- 收入,支持很大金额
);
-- 实际应用示例
INSERT INTO example_decimals (id, original_price, discount_price, final_price, average_rating)
VALUES (1, 299.00, 199.00, 199.00, 4.75);
-- 计算示例
SELECT
original_price,
discount_price,
final_price,
(original_price - final_price) AS discount_amount, -- 折扣金额
((original_price - final_price) / original_price * 100) AS discount_percent -- 折扣百分比
FROM example_decimals
WHERE id = 1;
2.2 日期和时间类型
专业性描述
MySQL的日期和时间类型用于存储日期、时间或日期时间值。这些类型包括DATE、TIME、DATETIME、TIMESTAMP、YEAR等。不同的类型有不同的存储空间和精度,适用于不同的应用场景。
日期时间类型对比
| 类型 |
格式 |
范围 |
存储空间 |
特点 |
智慧学堂应用 |
| DATE |
YYYY-MM-DD |
1000-01-01 ~ 9999-12-31 |
3字节 |
只存储日期 |
用户生日、课程开始日期 |
| TIME |
HH:MM:SS[.fraction] |
-838:59:59 ~ 838:59:59 |
3字节+小数 |
存储时间或时间间隔 |
课程时长、学习时间 |
| DATETIME |
YYYY-MM-DD HH:MM:SS[.fraction] |
1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 |
5字节+小数 |
日期和时间,与时区无关 |
订单创建时间、课程发布时间 |
| TIMESTAMP |
YYYY-MM-DD HH:MM:SS[.fraction] |
1970-01-01 00:00:01 ~ 2038-01-19 03:14:07 |
4字节+小数 |
日期时间,自动时区转换 |
记录创建/更新时间、登录时间 |
| YEAR |
YYYY |
1901 ~ 2155 |
1字节 |
存储年份 |
入学年份、毕业年份 |
日期时间类型使用示例
-- 创建包含各种日期时间类型的表
CREATE TABLE example_datetimes (
id INT PRIMARY KEY AUTO_INCREMENT,
-- 日期相关
birth_date DATE, -- 出生日期
course_start_date DATE, -- 课程开始日期
course_end_date DATE, -- 课程结束日期
-- 时间相关
lesson_duration TIME, -- 课时时长
daily_study_time TIME, -- 每日学习时间
total_study_time TIME, -- 总学习时间
-- 日期时间相关
published_at DATETIME, -- 发布时间
last_login_at DATETIME, -- 最后登录时间
order_created_at DATETIME(3), -- 订单创建时间(毫秒精度)
-- 时间戳(自动更新)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间
ON UPDATE CURRENT_TIMESTAMP,
-- 年份
enrollment_year YEAR, -- 入学年份
graduation_year YEAR -- 毕业年份
);
-- 插入数据
INSERT INTO example_datetimes (
birth_date, course_start_date, course_end_date,
lesson_duration, daily_study_time,
published_at, last_login_at, order_created_at,
enrollment_year, graduation_year
) VALUES (
'1990-05-15', -- 出生日期
'2024-01-15', -- 课程开始日期
'2024-06-15', -- 课程结束日期
'01:30:00', -- 课时时长1小时30分
'02:15:30', -- 每日学习2小时15分30秒
'2024-01-10 09:30:00', -- 发布时间
'2024-01-20 14:25:10', -- 最后登录时间
'2024-01-15 10:30:15.123', -- 订单创建时间(含毫秒)
2024, -- 入学年份
2026 -- 毕业年份
);
-- 查询示例
SELECT
-- 日期计算
birth_date,
YEAR(CURDATE()) - YEAR(birth_date) AS age, -- 计算年龄
-- 时间计算
lesson_duration,
SEC_TO_TIME(TIME_TO_SEC(lesson_duration) * 2) AS double_duration, -- 时长翻倍
-- 日期时间计算
published_at,
DATE_ADD(published_at, INTERVAL 7 DAY) AS one_week_later, -- 一周后
-- 时间差计算
TIMESTAMPDIFF(DAY, course_start_date, course_end_date) AS course_days, -- 课程天数
-- 格式化输出
DATE_FORMAT(published_at, '%Y年%m月%d日 %H:%i:%s') AS formatted_date
FROM example_datetimes;
-- 实用查询:查找最近7天的活跃用户
SELECT
u.username,
COUNT(DISTINCT DATE(l.login_time)) AS active_days
FROM users u
JOIN user_logins l ON u.id = l.user_id
WHERE l.login_time >= DATE_SUB(NOW(), INTERVAL 7 DAY)
GROUP BY u.id
HAVING active_days >= 3; -- 7天内至少活跃3天
2.3 字符串类型
专业性描述
MySQL的字符串类型用于存储文本数据,包括定长字符串、变长字符串、文本类型等。不同类型的字符串在存储方式、性能和最大长度上有所不同,需要根据实际需求选择合适的类型。
字符串类型对比
| 类型 |
最大长度 |
存储特点 |
性能 |
智慧学堂应用 |
| CHAR(N) |
255字符 |
定长,不足补空格 |
查询快,存储可能浪费 |
固定长度的编码、状态码 |
| VARCHAR(N) |
65535字节 |
变长,按实际长度存储 |
存储节省,查询稍慢 |
用户名、邮箱、标题等变长文本 |
| TINYTEXT |
255字节 |
变长文本 |
存储小段文本 |
短描述、备注 |
| TEXT |
65535字节 |
变长文本 |
存储中等长度文本 |
课程描述、文章内容 |
| MEDIUMTEXT |
16777215字节 |
变长文本 |
存储较长文本 |
详细说明、长文章 |
| LONGTEXT |
4294967295字节 |
变长文本 |
存储极长文本 |
电子书、大量日志 |
字符串类型使用示例
-- 字符串类型使用示例
CREATE TABLE example_strings (
id INT PRIMARY KEY AUTO_INCREMENT,
-- 定长字符串
country_code CHAR(2) DEFAULT 'CN', -- 国家代码,固定2位
user_type CHAR(1) DEFAULT 'S', -- 用户类型,S-学生,T-老师
status_code CHAR(3) DEFAULT 'ACT', -- 状态码,固定3位
-- 变长字符串
username VARCHAR(50) NOT NULL UNIQUE, -- 用户名,最长50字符
email VARCHAR(100) NOT NULL UNIQUE, -- 邮箱,最长100字符
phone VARCHAR(20), -- 手机号
title VARCHAR(200) NOT NULL, -- 标题,最长200字符
description VARCHAR(500), -- 描述,最长500字符
-- 文本类型
short_bio TINYTEXT, -- 简短介绍
course_description TEXT, -- 课程描述
long_article MEDIUMTEXT, -- 长篇文章
ebook_content LONGTEXT, -- 电子书内容
-- 其他字符串类型
gender ENUM('male', 'female', 'unknown') DEFAULT 'unknown', -- 枚举
interests SET('coding', 'reading', 'music', 'sports') -- 集合
-- 注意:实际存储时考虑字符集,中文在utf8mb4中占3-4字节
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 插入数据
INSERT INTO example_strings (
country_code, user_type, status_code,
username, email, phone, title, description,
short_bio, course_description
) VALUES (
'CN', 'S', 'ACT', -- 定长字段
'张三同学', 'zhangsan@example.com', -- 变长字段
'13800138000', 'Python编程入门',
'从零开始学习Python编程语言,适合初学者',
'热爱编程的大学生', -- 短文本
'本课程面向零基础学员,通过实际案例讲解Python基础语法、数据结构、函数编程等核心知识。课程包含大量练习和实战项目,帮助学员快速掌握Python编程技能。' -- 文本
);
-- 字符串函数示例
SELECT
username,
-- 字符串长度
CHAR_LENGTH(username) AS char_length, -- 字符数
LENGTH(username) AS byte_length, -- 字节数
-- 字符串操作
CONCAT(username, '(', email, ')') AS user_info, -- 连接
UPPER(username) AS upper_name, -- 大写
LOWER(email) AS lower_email, -- 小写
SUBSTRING(email, 1, LOCATE('@', email) - 1) AS email_prefix, -- 子串
-- 字符串查找
INSTR(description, 'Python') AS python_position, -- 查找位置
-- 字符串替换
REPLACE(description, 'Python', 'Python语言') AS replaced_desc,
-- 去除空格
TRIM(' ' FROM username) AS trimmed_name
FROM example_strings
WHERE id = 1;
-- 实用查询:搜索包含关键词的课程
SELECT
id,
title,
description,
-- 高亮显示搜索关键词
REPLACE(
REPLACE(
description,
'Python',
'**Python**'
),
'编程',
'**编程**'
) AS highlighted_desc
FROM courses
WHERE
title LIKE '%Python%'
OR description LIKE '%Python%'
OR description LIKE '%编程%'
LIMIT 10;
字符集和排序规则
-- 查看MySQL支持的字符集
SHOW CHARACTER SET;
-- 查看支持的中文字符集
SHOW CHARACTER SET LIKE '%utf8%';
-- 创建表时指定字符集
CREATE TABLE example_charset (
id INT PRIMARY KEY,
name VARCHAR(100)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4 -- 支持所有Unicode字符,包括emoji
COLLATE=utf8mb4_unicode_ci; -- 不区分大小写的排序规则
-- 常用字符集说明
-- utf8mb3: 基本多文种平面字符,3字节/字符
-- utf8mb4: 支持所有Unicode字符,包括emoji,4字节/字符
-- gbk: 简体中文,2字节/中文字符
-- latin1: 西欧字符,1字节/字符
-- 常用排序规则说明
-- _ci: 不区分大小写 (case insensitive)
-- _cs: 区分大小写 (case sensitive)
-- _bin: 二进制比较
-- _unicode_ci: 基于Unicode的排序,不区分大小写
-- _general_ci: 一般排序规则,不区分大小写
-- 修改表字符集
ALTER TABLE example_charset
CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 查询字符集信息
SELECT
TABLE_SCHEMA,
TABLE_NAME,
TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_NAME = 'example_charset';
2.4 二进制类型
专业性描述
MySQL的二进制类型用于存储二进制数据,如图片、音频、视频、压缩文件等。这些类型以字节形式存储数据,不进行字符集转换。二进制类型包括BINARY、VARBINARY、BLOB系列等。
二进制类型对比
| 类型 |
最大长度 |
存储特点 |
智慧学堂应用 |
| BINARY(N) |
255字节 |
定长二进制数据 |
固定长度的加密数据、哈希值 |
| VARBINARY(N) |
65535字节 |
变长二进制数据 |
变长的加密数据、签名 |
| TINYBLOB |
255字节 |
小二进制对象 |
小图片、图标、配置数据 |
| BLOB |
65535字节 |
二进制大对象 |
中等大小的文件、文档 |
| MEDIUMBLOB |
16777215字节 |
中等二进制对象 |
较大的图片、音频、PDF |
| LONGBLOB |
4294967295字节 |
大二进制对象 |
视频、大型文件、备份 |
二进制类型使用示例
-- 创建包含二进制类型的表
CREATE TABLE example_binary (
id INT PRIMARY KEY AUTO_INCREMENT,
-- 二进制数据
password_hash BINARY(64), -- 密码哈希,固定64字节
file_signature VARBINARY(256), -- 文件签名,变长
config_data TINYBLOB, -- 小配置文件
avatar_image BLOB, -- 头像图片
certificate_file MEDIUMBLOB, -- 证书文件
video_preview LONGBLOB, -- 视频预览(实际不推荐存DB)
-- 文件元数据
file_name VARCHAR(255),
file_size INT UNSIGNED,
mime_type VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 注意:实际应用中,大文件通常不直接存储在数据库中
-- 而是存储在文件系统或对象存储中,数据库中只存储文件路径
-- 更合理的做法:存储文件路径
CREATE TABLE user_files (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
file_type ENUM('avatar', 'certificate', 'other'),
file_path VARCHAR(500) NOT NULL, -- 文件存储路径
file_url VARCHAR(500) NOT NULL, -- 文件访问URL
file_name VARCHAR(255) NOT NULL,
file_size INT UNSIGNED,
mime_type VARCHAR(100),
storage_type ENUM('local', 'oss', 'cos') DEFAULT 'local',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id),
INDEX idx_user_id (user_id)
);
-- 二进制函数示例
SET @hash_value = UNHEX(SHA2('my_password', 256)); -- 生成SHA256哈希
INSERT INTO example_binary (password_hash, file_signature)
VALUES (
@hash_value, -- 密码哈希
UNHEX(MD5('file_content')) -- 文件MD5签名
);
-- 查询二进制数据
SELECT
id,
-- 将二进制转换为十六进制字符串显示
HEX(password_hash) AS password_hash_hex,
HEX(file_signature) AS signature_hex,
-- 获取二进制长度
LENGTH(password_hash) AS hash_length,
LENGTH(file_signature) AS signature_length
FROM example_binary
WHERE id = 1;
-- 二进制数据比较
SELECT
CASE
WHEN password_hash = UNHEX('abc123...') THEN '匹配'
ELSE '不匹配'
END AS hash_match
FROM example_binary
WHERE id = 1;
2.5 空间数据类型
专业性描述
MySQL的空间数据类型用于存储地理空间数据,支持OpenGIS规范。这些类型可以存储点、线、多边形等几何对象,并支持空间索引和空间函数。MySQL 5.7及以上版本对空间数据有较好的支持。
空间数据类型
| 类型 |
描述 |
示例 |
智慧学堂应用 |
| GEOMETRY |
所有空间类型的基类 |
任意几何图形 |
通用地理数据存储 |
| POINT |
点 |
POINT(116.404, 39.915) |
用户位置、学校位置 |
| LINESTRING |
线 |
LINESTRING(0 0,1 1,2 2) |
配送路线、通勤路线 |
| POLYGON |
多边形 |
POLYGON((0 0,10 0,10 10,0 10,0 0)) |
校区范围、服务区域 |
| MULTIPOINT |
多点集合 |
MULTIPOINT(0 0, 20 20, 60 60) |
多个分支机构位置 |
| MULTILINESTRING |
多线集合 |
多条路线集合 |
多条公交线路 |
| MULTIPOLYGON |
多多边形集合 |
多个区域集合 |
多个校区范围 |
| GEOMETRYCOLLECTION |
几何对象集合 |
多种类型组合 |
复杂地理数据 |
空间数据类型使用示例
-- 创建包含空间数据的表
CREATE TABLE example_spatial (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
-- 各种空间类型
location POINT SRID 4326, -- 点位置,WGS84坐标系
campus_area POLYGON SRID 4326, -- 多边形区域
delivery_route LINESTRING SRID 4326, -- 配送路线
-- 空间索引
SPATIAL INDEX idx_location (location),
SPATIAL INDEX idx_campus_area (campus_area)
) ENGINE=InnoDB;
-- 插入空间数据
INSERT INTO example_spatial (name, location, campus_area, delivery_route)
VALUES (
'北京总部',
ST_GeomFromText('POINT(116.404 39.915)', 4326), -- 北京坐标
-- 多边形(矩形区域)
ST_GeomFromText('POLYGON((116.40 39.91, 116.41 39.91, 116.41 39.92, 116.40 39.92, 116.40 39.91))', 4326),
-- 路线
ST_GeomFromText('LINESTRING(116.404 39.915, 116.405 39.916, 116.406 39.917)', 4326)
);
-- 插入多个地点
INSERT INTO example_spatial (name, location) VALUES
('上海分部', ST_GeomFromText('POINT(121.473 31.230)', 4326)),
('广州分部', ST_GeomFromText('POINT(113.264 23.129)', 4326)),
('深圳分部', ST_GeomFromText('POINT(114.057 22.543)', 4326));
-- 空间查询示例
SELECT
name,
-- 获取WKT格式
ST_AsText(location) AS location_wkt,
-- 获取坐标
ST_X(location) AS longitude, -- 经度
ST_Y(location) AS latitude, -- 纬度
-- 计算距离(米)
ST_Distance_Sphere(
location,
ST_GeomFromText('POINT(116.404 39.915)', 4326)
) AS distance_from_beijing,
-- 判断是否在区域内
ST_Contains(
ST_GeomFromText('POLYGON((116.30 39.80, 116.50 39.80, 116.50 40.00, 116.30 40.00, 116.30 39.80))', 4326),
location
) AS is_in_beijing_area
FROM example_spatial;
-- 查找附近的地点(10公里内)
SELECT
name,
ST_Distance_Sphere(location, @my_location) AS distance_meters
FROM example_spatial
WHERE ST_Distance_Sphere(location, @my_location) <= 10000 -- 10公里
ORDER BY distance_meters;
-- 计算多边形的面积
SELECT
name,
ST_Area(campus_area) AS raw_area, -- 球面面积(平方度)
ST_Area(campus_area, 'metre') AS area_m2 -- 平方米
FROM example_spatial
WHERE campus_area IS NOT NULL;
2.6 JSON数据类型
专业性描述
MySQL 5.7及以上版本支持JSON数据类型,用于存储JSON格式的数据。JSON类型提供了自动验证、高效存储和查询功能。它结合了关系数据库的结构化优势和NoSQL的灵活性。
JSON类型特点
| 特点 |
描述 |
优势 |
| 自动验证 |
插入时会验证JSON格式 |
保证数据有效性 |
| 高效存储 |
二进制格式存储,访问快 |
查询性能好 |
| 索引支持 |
支持在JSON字段上创建索引 |
加速查询 |
| 丰富函数 |
提供大量JSON操作函数 |
灵活处理数据 |
JSON类型使用示例
-- 创建包含JSON类型的表
CREATE TABLE example_json (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
-- JSON数据
profile JSON, -- 用户扩展信息
settings JSON, -- 用户设置
course_progress JSON, -- 课程进度
metadata JSON, -- 元数据
-- 在JSON字段上创建索引
INDEX idx_user_id (user_id),
INDEX idx_profile_email ((CAST(profile->>'$.email' AS CHAR(100)))),
-- 外键约束
FOREIGN KEY (user_id) REFERENCES users(id)
);
-- 插入JSON数据
INSERT INTO example_json (user_id, profile, settings, course_progress)
VALUES (
1001,
-- 用户扩展信息
'{
"real_name": "张三",
"gender": "male",
"birthday": "1990-05-15",
"email": "zhangsan@example.com",
"address": {
"province": "北京",
"city": "北京市",
"district": "海淀区",
"detail": "中关村大街1号"
},
"education": {
"degree": "本科",
"school": "北京大学",
"major": "计算机科学"
}
}',
-- 用户设置
'{
"notification": {
"email": true,
"sms": false,
"push": true
},
"privacy": {
"show_real_name": false,
"show_email": false
},
"preferences": {
"theme": "light",
"language": "zh-CN"
}
}',
-- 课程进度
'{
"course_1001": {
"progress": 75.5,
"last_lesson": 15,
"completed_lessons": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
"test_scores": {
"quiz_1": 85,
"quiz_2": 92,
"final_exam": 78
},
"study_time": 1250
},
"course_1002": {
"progress": 30.0,
"last_lesson": 5,
"completed_lessons": [1, 2, 3, 4, 5],
"study_time": 320
}
}'
);
-- JSON查询示例
SELECT
id,
user_id,
-- 提取JSON字段
profile->>'$.real_name' AS real_name, -- 提取姓名
profile->>'$.email' AS email, -- 提取邮箱
profile->>'$.address.city' AS city, -- 提取城市
-- 提取嵌套字段
JSON_EXTRACT(profile, '$.education.degree') AS degree,
-- 判断是否包含字段
JSON_CONTAINS_PATH(profile, 'one', '$.education') AS has_education,
-- 获取数组长度
JSON_LENGTH(course_progress, '$.course_1001.completed_lessons') AS completed_count,
-- 提取数组元素
course_progress->>'$.course_1001.completed_lessons[0]' AS first_completed
FROM example_json
WHERE user_id = 1001;
-- 复杂JSON查询
SELECT
user_id,
-- 提取所有课程进度
JSON_KEYS(course_progress) AS course_ids,
-- 计算总学习进度
(
SELECT AVG(progress)
FROM JSON_TABLE(
JSON_KEYS(course_progress),
'$' COLUMNS(course_id VARCHAR(20) PATH '$')
) AS courses
JOIN JSON_TABLE(
course_progress,
'$.*' COLUMNS(
progress DECIMAL(5,2) PATH '$.progress'
)
) AS progresses
) AS avg_progress,
-- 提取通知设置
settings->>'$.notification.email' AS email_notification
FROM example_json
WHERE JSON_EXTRACT(settings, '$.notification.email') = 'true';
-- 更新JSON数据
UPDATE example_json
SET
-- 修改JSON字段
profile = JSON_SET(
profile,
'$.phone', '13800138000', -- 添加/修改电话
'$.address.district', '朝阳区' -- 修改区域
),
-- 删除JSON字段
settings = JSON_REMOVE(settings, '$.privacy.show_email'),
-- 数组合并
course_progress = JSON_SET(
course_progress,
'$.course_1001.completed_lessons',
JSON_ARRAY_APPEND(
course_progress->>'$.course_1001.completed_lessons',
'$',
16
)
)
WHERE user_id = 1001;
-- 创建生成列和索引
ALTER TABLE example_json
ADD COLUMN email_from_profile VARCHAR(100)
GENERATED ALWAYS AS (profile->>'$.email') VIRTUAL,
ADD INDEX idx_email_from_profile (email_from_profile);
-- 使用生成列查询
SELECT * FROM example_json
WHERE email_from_profile = 'zhangsan@example.com';
2.7 选择数据类型的依据
专业性描述
选择合适的数据类型需要考虑数据的特性、存储需求、查询性能、数据完整性等因素。合理的数据类型选择可以节省存储空间、提高查询性能、保证数据准确性。
选择原则
-
最小原则:使用能满足需求的最小数据类型
示例:状态字段用TINYINT而不是INT,性别用ENUM而不是VARCHAR
-
简单原则:简单数据类型优先
示例:日期用DATE而不是VARCHAR,数字用INT而不是VARCHAR
-
避免NULL:尽量使用NOT NULL
示例:username VARCHAR(50) NOT NULL DEFAULT ''
-
字符集统一:使用一致的字符集
示例:全部使用utf8mb4,避免乱码
常见数据类型选择错误与改进
| 错误用法 |
问题 |
改进方案 |
理由 |
| phone VARCHAR(255) |
存储空间浪费 |
phone VARCHAR(20) |
手机号最长20字符足够 |
| status VARCHAR(10) |
无验证,可能输入错误 |
status ENUM('active','inactive') |
确保只有有效状态 |
| price FLOAT |
精度问题,计算误差 |
price DECIMAL(10,2) |
精确计算金额 |
| birth_date VARCHAR(20) |
无法进行日期计算 |
birth_date DATE |
支持日期函数和计算 |
| is_deleted INT |
存储空间浪费 |
is_deleted TINYINT(1) |
0/1值只需1字节 |
| content VARCHAR(10000) |
VARCHAR最大65535字节 |
content TEXT |
适合长文本存储 |
实际项目中的数据类型规范
-- 智慧学堂数据库设计规范示例
-- 1. 主键规范
-- 使用INT UNSIGNED AUTO_INCREMENT,除非需要分布式ID
CREATE TABLE example_standard (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, -- 主键
...
);
-- 2. 时间字段规范
CREATE TABLE example_timestamps (
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 创建时间
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 更新时间
ON UPDATE CURRENT_TIMESTAMP,
deleted_at TIMESTAMP NULL DEFAULT NULL, -- 软删除时间
...
);
-- 3. 状态字段规范
-- 使用TINYINT UNSIGNED,注释说明含义
CREATE TABLE example_status (
status TINYINT UNSIGNED NOT NULL DEFAULT 1 COMMENT '1-正常 2-禁用 3-删除',
verify_status TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0-未验证 1-已验证 2-验证失败',
...
);
-- 4. 金额字段规范
CREATE TABLE example_money (
price DECIMAL(10, 2) NOT NULL DEFAULT 0.00 COMMENT '价格,单位:元',
discount DECIMAL(5, 2) NOT NULL DEFAULT 0.00 COMMENT '折扣,0.00-1.00',
amount DECIMAL(12, 2) NOT NULL DEFAULT 0.00 COMMENT '金额,单位:元',
...
);
-- 5. 字符字段规范
CREATE TABLE example_strings (
-- 定长编码
country_code CHAR(2) NOT NULL DEFAULT 'CN' COMMENT '国家代码,ISO 3166',
-- 变长字段
username VARCHAR(50) NOT NULL COMMENT '用户名,3-50字符',
email VARCHAR(100) NOT NULL COMMENT '邮箱',
mobile CHAR(11) COMMENT '手机号,11位数字',
-- 文本
description VARCHAR(500) COMMENT '描述,最多500字符',
content TEXT COMMENT '内容',
-- 索引
UNIQUE KEY uk_username (username),
UNIQUE KEY uk_email (email),
INDEX idx_mobile (mobile)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 6. 枚举字段规范
CREATE TABLE example_enum (
gender ENUM('male', 'female', 'unknown') NOT NULL DEFAULT 'unknown',
user_type ENUM('student', 'teacher', 'admin') NOT NULL DEFAULT 'student',
...
);
-- 7. 软删除规范
-- 查询时自动过滤已删除数据
CREATE VIEW v_active_users AS
SELECT * FROM users WHERE deleted_at IS NULL;
-- 8. 默认值和注释规范
CREATE TABLE example_comments (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序,越大越靠前',
is_top TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否置顶:0-否 1-是',
view_count INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '浏览次数',
like_count INT UNSIGNED NOT NULL DEFAULT 0 COMMENT '点赞数',
...
) COMMENT='示例表,展示规范写法';
3. 记忆技巧与实战要点
核心口诀:
MySQL数据库,关系型存储好。
核心概念要记牢,表字段记录和索引。
SQL分四类,DDL、DML、DQL、DCL。
数据类型多,数值文本日期二进制。
选择有依据,最小简单避NULL是原则。
智慧学堂是典型,MySQL应用要熟练。
总结
MySQL是一个功能强大、应用广泛的关系型数据库管理系统。掌握MySQL的核心概念、SQL语言和各种数据类型,对于构建稳定高效的应用程序至关重要。
通过DDL语句设计数据库结构,通过DML语句操作数据,通过DQL语句查询信息,通过合适的数据类型确保数据准确性和存储效率。正确选择数据类型不仅可以节省存储空间,还能提高查询性能。
记住选择数据类型的基本原则:最小、简单、避免NULL、字符集统一。通过规范的数据类型选择和合理的数据库设计,我们可以构建出稳定、高效、可维护的数据库系统,为应用程序提供坚实的数据支撑。
希望这篇结合“智慧学堂”场景的详细解析,能帮助你更好地理解和应用MySQL。如果你在实践中有更多心得或问题,欢迎在 云栈社区 与其他开发者交流探讨。