MySQL基础核心知识点
1. 存储引擎(MySQL的"表的存储方式")
存储引擎是MySQL中处理表的底层软件组件,不同引擎有不同特性,核心区别如下:
| 存储引擎 | 事务支持 | 外键约束 | 行级锁 | 适用场景 |
|---|---|---|---|---|
| InnoDB | ✅(ACID) | ✅ | ✅ | 业务系统(订单、用户表) |
| MyISAM | ❌ | ❌ | ❌(表锁) | 只读/少写场景(日志、统计) |
| MEMORY | ❌ | ❌ | ✅ | 临时数据(缓存、会话表) |
-
默认引擎:MySQL 5.5+ 默认是InnoDB,也是开发中唯一推荐使用的引擎(支持事务、外键、崩溃恢复)。
-
查看/设置引擎 :
sql-- 查看表的存储引擎 SHOW TABLE STATUS LIKE 'student'\G; -- 创建表时指定引擎(显式声明,推荐) CREATE TABLE student (id INT) ENGINE=InnoDB;
2. 核心数据类型(表字段的"数据格式")
MySQL数据类型决定了字段能存储的数据类型和范围,常用类型如下:
| 类型分类 | 常用类型 | 说明 |
|---|---|---|
| 数值型 | INT(整数) | 存储整数(-2^31 ~ 2^31-1),如学生ID |
| TINYINT UNSIGNED | 无符号小整数(0~255),如分数、年龄 | |
| DECIMAL(M,D) | 高精度小数(M总位数,D小数位),如金额 | |
| 字符串型 | VARCHAR(M) | 可变长度字符串(M最大长度),如姓名 |
| CHAR(M) | 固定长度字符串,如手机号(11位) | |
| TEXT | 长文本(如备注、文章内容) | |
| 日期型 | DATETIME | 日期+时间('YYYY-MM-DD HH:MM:SS') |
| DATE | 仅日期('YYYY-MM-DD') | |
| TIMESTAMP | 时间戳(自动更新,时区敏感) |
3. 约束(保证数据的"正确性和完整性")
约束是对表字段的规则限制,核心约束如下:
| 约束类型 | 关键字 | 说明 |
|---|---|---|
| 主键 | PRIMARY KEY | 唯一标识行,非空+唯一,一张表只能有1个 |
| 外键 | FOREIGN KEY | 关联另一张表的主键,保证数据一致性 |
| 非空 | NOT NULL | 字段值不能为NULL |
| 唯一 | UNIQUE | 字段值唯一(可多个NULL) |
| 默认 | DEFAULT | 字段未赋值时的默认值 |
4. 字符集与排序规则
-
字符集 :决定MySQL能存储的字符范围,推荐
utf8mb4(兼容utf8,且支持emoji、特殊字符)。 -
排序规则 :决定字符的比较/排序方式,推荐
utf8mb4_general_ci(不区分大小写,性能好)。 -
查看/设置 :
sql-- 查看数据库字符集 SHOW CREATE DATABASE school_db; -- 创建数据库时指定 CREATE DATABASE school_db CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
5. 事务(InnoDB核心特性)
事务是一组不可分割的SQL操作,要么全部执行成功,要么全部失败,遵循ACID原则:
- 原子性(A):操作要么全成,要么全回滚;
- 一致性(C):事务前后数据完整性不变;
- 隔离性(I):多个事务互不干扰;
- 持久性(D):提交后数据永久保存。
示例表准备(所有SQL示例基于此)
先创建数据库和基础表,确保示例可直接运行:
sql
-- 1. 创建数据库(指定字符集)
CREATE DATABASE IF NOT EXISTS school_db
CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
USE school_db; -- 切换到该数据库
-- 2. 创建学生表(含约束+注释)
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '学生ID(主键,自增)',
name VARCHAR(50) NOT NULL COMMENT '姓名(非空)',
age TINYINT UNSIGNED COMMENT '年龄(无符号)',
gender ENUM('男','女','未知') DEFAULT '未知' COMMENT '性别(枚举,默认未知)',
class_id INT COMMENT '班级ID',
phone CHAR(11) UNIQUE COMMENT '手机号(唯一)',
create_time DATETIME DEFAULT NOW() COMMENT '创建时间(默认当前时间)'
) ENGINE=InnoDB COMMENT '学生信息表';
-- 3. 创建成绩表(含外键)
CREATE TABLE score (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '成绩ID',
student_id INT NOT NULL COMMENT '关联学生ID',
subject VARCHAR(30) NOT NULL COMMENT '科目',
score TINYINT UNSIGNED COMMENT '分数(0-100)',
-- 外键约束:student_id必须存在于student表的id中,删除学生时同步删除成绩
FOREIGN KEY (student_id) REFERENCES student(id) ON DELETE CASCADE,
-- 联合唯一:同一学生不能重复选同一科目
UNIQUE KEY uk_stu_sub (student_id, subject)
) ENGINE=InnoDB COMMENT '学生成绩表';
常用SQL语句整理
一、DDL(数据定义语言):定义/修改数据库结构
用于创建、修改、删除数据库、表、索引、视图等结构,操作不可逆,需谨慎。
1. 数据库相关DDL
| 语句 | 讲解 | 示例 |
|---|---|---|
| CREATE DATABASE | 创建数据库;IF NOT EXISTS避免重复创建;CHARSET指定字符集 | CREATE DATABASE IF NOT EXISTS test_db CHARSET utf8mb4; |
| USE | 切换到指定数据库(后续操作基于该库) | USE school_db; |
| ALTER DATABASE | 修改数据库字符集/排序规则 | ALTER DATABASE school_db COLLATE utf8mb4_bin;(区分大小写排序) |
| DROP DATABASE | 删除数据库(不可逆);IF EXISTS避免不存在时报错 | DROP DATABASE IF EXISTS test_db; |
| SHOW DATABASES | 查看所有数据库 | SHOW DATABASES; |
| SHOW CREATE DATABASE | 查看数据库的创建语句(含字符集、排序规则) | SHOW CREATE DATABASE school_db; |
2. 表相关DDL
(1)创建表
sql
-- 基础创建(含注释+引擎)
CREATE TABLE IF NOT EXISTS class (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '班级ID',
class_name VARCHAR(30) NOT NULL COMMENT '班级名称',
grade VARCHAR(10) COMMENT '年级'
) ENGINE=InnoDB COMMENT '班级表';
-- 复制表结构(仅结构,无数据)
CREATE TABLE student_copy LIKE student;
-- 复制表结构+数据
CREATE TABLE student_2024 AS SELECT * FROM student WHERE class_id = 1;
(2)修改表结构(ALTER TABLE)
| 操作 | 语法示例 | 讲解 |
|---|---|---|
| 添加字段 | ALTER TABLE student ADD email VARCHAR(50) AFTER phone; |
AFTER指定字段位置,FIRST放第一个,默认最后 |
| 修改字段类型/约束 | ALTER TABLE student MODIFY phone VARCHAR(11) NOT NULL; |
MODIFY只改类型/约束,不改字段名 |
| 重命名字段 | ALTER TABLE student CHANGE email stu_email VARCHAR(50) UNIQUE; |
CHANGE可同时改字段名和类型/约束 |
| 删除字段 | ALTER TABLE student DROP COLUMN stu_email; |
不可逆,删除前确认数据 |
| 添加主键 | ALTER TABLE class ADD PRIMARY KEY (id); |
若表无主键,可添加(一张表仅1个) |
| 添加外键 | ALTER TABLE score ADD FOREIGN KEY (student_id) REFERENCES student(id); |
外键依赖主键,仅InnoDB支持 |
| 删除外键 | ALTER TABLE score DROP FOREIGN KEY 外键名; |
先通过SHOW CREATE TABLE score查外键名,再删除 |
| 添加唯一约束 | ALTER TABLE student ADD UNIQUE KEY uk_name (name); |
给name字段加唯一约束 |
| 重命名表 | ALTER TABLE class RENAME TO grade_class;(或RENAME TABLE) |
两种方式均可,RENAME TABLE更简洁 |
(3)删除/清空表
| 语句 | 示例 | 讲解 |
|---|---|---|
| DROP TABLE | DROP TABLE IF EXISTS class; |
删除表(结构+数据,不可逆) |
| TRUNCATE TABLE | TRUNCATE TABLE score; |
清空数据(DDL,不可回滚),重置自增主键,比DELETE快 |
| SHOW TABLES | SHOW TABLES; |
查看当前数据库的所有表 |
| DESC/EXPLAIN | DESC student; |
查看表结构(字段名、类型、约束等) |
| SHOW CREATE TABLE | SHOW CREATE TABLE student\G; |
查看表的完整创建语句(含引擎、字符集、索引、约束) |
3. 索引相关DDL(提升查询效率)
索引是"表的目录",加速查询但降低插入/更新速度,仅给常用查询字段加。
| 索引类型 | 示例 | 讲解 |
|---|---|---|
| 普通索引 | CREATE INDEX idx_student_class ON student(class_id); |
最常用,无唯一性限制 |
| 唯一索引 | CREATE UNIQUE INDEX idx_student_phone ON student(phone); |
字段值唯一,重复插入会报错 |
| 联合索引 | CREATE INDEX idx_score_stu_sub ON score(student_id, subject); |
多字段组合索引,遵循"最左匹配"(查询时优先用左字段) |
| 主键索引 | 建表时PRIMARY KEY自动创建 | 特殊的唯一索引,非空+唯一 |
| 删除索引 | DROP INDEX idx_student_class ON student; |
无需索引时删除,减少写入开销 |
| 查看索引 | SHOW INDEX FROM student; |
查看表的所有索引信息 |
4. 视图相关DDL(虚拟表)
视图是基于查询结果的虚拟表,简化复杂查询,不存储数据(仅存储查询逻辑)。
sql
-- 创建视图(展示学生+班级+成绩)
CREATE VIEW v_student_full AS
SELECT s.name, c.class_name, sc.subject, sc.score
FROM student s
LEFT JOIN class c ON s.class_id = c.id
LEFT JOIN score sc ON s.id = sc.student_id;
-- 修改视图
CREATE OR REPLACE VIEW v_student_full AS
SELECT s.name, c.class_name, sc.subject, sc.score, s.age
FROM student s
LEFT JOIN class c ON s.class_id = c.id
LEFT JOIN score sc ON s.id = sc.student_id;
-- 删除视图
DROP VIEW IF EXISTS v_student_full;
-- 查看视图
SHOW VIEWS;
二、DML(数据操作语言):操作表中数据
用于插入、更新、删除表数据,属于"可回滚操作"(事务中),核心语句:INSERT/UPDATE/DELETE。
1. INSERT(插入数据)
| 插入方式 | 示例 | 讲解 |
|---|---|---|
| 单行插入(指定字段) | INSERT INTO student(name, age, gender, class_id, phone) VALUES('张三', 18, '男', 1, '13800138000'); |
推荐方式,字段顺序可自定义,未指定的字段用默认值/NULL |
| 单行插入(所有字段) | INSERT INTO student VALUES(NULL, '李四', 17, '女', 2, '13900139000', NOW()); |
需按表字段顺序,自增主键填NULL(自动生成) |
| 多行插入 | INSERT INTO student(name, age, class_id) VALUES('王五', 18, 1), ('赵六', 19, 2), ('钱七', 17, 2); |
批量插入,比单行插入效率高 |
| 从查询结果插入 | INSERT INTO score(student_id, subject, score) SELECT id, '语文', 85 FROM student WHERE class_id = 1; |
将查询结果批量插入,需字段数量/类型匹配 |
2. UPDATE(更新数据)
核心:必须加WHERE条件,否则修改全表数据!
sql
-- 单表更新(基础)
UPDATE student SET age = 19 WHERE name = '张三';
-- 多字段更新
UPDATE student SET age = age + 1, gender = '男' WHERE class_id = 2;
-- 关联表更新(根据成绩更新学生信息)
UPDATE student s
JOIN score sc ON s.id = sc.student_id
SET s.age = s.age + 1
WHERE sc.subject = '数学' AND sc.score > 90;
-- 安全更新(避免误更全表):开启后UPDATE/DELETE必须加WHERE
SET SQL_SAFE_UPDATES = 1;
3. DELETE(删除数据)
核心:必须加WHERE条件,否则删除全表数据!
sql
-- 单表删除
DELETE FROM student WHERE name = '钱七';
-- 关联表删除(删除无成绩的学生)
DELETE s FROM student s
LEFT JOIN score sc ON s.id = sc.student_id
WHERE sc.id IS NULL;
-- 清空数据(DML方式,可回滚)
DELETE FROM score; -- 区别于TRUNCATE:不重置自增主键,可回滚
三、DQL(数据查询语言):查询数据
SELECT是MySQL最常用语句,覆盖基础查询、复杂关联查询、聚合分析等,语法结构:
SELECT [DISTINCT] 字段/聚合函数
FROM 表1
[JOIN 表2 ON 关联条件]
[WHERE 行过滤条件]
[GROUP BY 分组字段]
[HAVING 分组过滤条件]
[ORDER BY 排序字段 [ASC/DESC]]
[LIMIT 偏移量, 行数];
1. 基础查询
| 操作 | 示例 | 讲解 |
|---|---|---|
| 查询指定字段 | SELECT name, age, class_id FROM student; |
推荐指定字段,避免SELECT *(性能差、易出问题) |
| 查询所有字段 | SELECT * FROM student; |
仅测试/临时查询用,生产环境禁用 |
| 去重查询 | SELECT DISTINCT class_id FROM student; |
去除重复的班级ID |
| 字段别名 | SELECT name AS 姓名, age AS 年龄 FROM student; |
AS可省略,别名含空格/特殊字符需加引号(SELECT name AS '学生姓名') |
| 字段运算 | SELECT name, score + 5 AS 加分后分数 FROM score WHERE subject = '数学'; |
对字段做算术运算(+/-/*//) |
2. 条件查询(WHERE)
常用条件运算符:
| 运算符类型 | 示例 | 讲解 |
|---|---|---|
| 比较运算 | age > 18、score <> 80 |
<>是不等于(也可用!=),=是等于 |
| 范围运算 | age BETWEEN 17 AND 19 |
包含边界值,等价于age >=17 AND age <=19 |
| 集合运算 | class_id IN (1,2) |
匹配集合中的值,等价于class_id=1 OR class_id=2 |
| 模糊查询 | name LIKE '张%' |
%匹配任意长度字符,_匹配单个字符;name LIKE '张_'匹配"张三",不匹配"张三丰" |
| 空值判断 | phone IS NULL |
空值用IS NULL,非空用IS NOT NULL(不能用=NULL) |
| 逻辑运算 | gender='男' AND class_id=1 |
AND(且)、OR(或)、NOT(非),优先级:NOT > AND > OR |
示例:
sql
-- 查询1班/2班、姓名含"李"、年龄17-19的女生
SELECT * FROM student
WHERE class_id IN (1,2)
AND name LIKE '%李%'
AND age BETWEEN 17 AND 19
AND gender = '女';
-- 查询手机号非空、性别不是未知的学生
SELECT * FROM student WHERE phone IS NOT NULL AND NOT gender = '未知';
3. 排序(ORDER BY)
sql
-- 单字段排序(降序)
SELECT * FROM score WHERE subject = '数学' ORDER BY score DESC;
-- 多字段排序(先按班级升序,再按年龄降序)
SELECT * FROM student ORDER BY class_id ASC, age DESC;
-- 按聚合结果排序(按每个班级的学生数降序)
SELECT class_id, COUNT(*) AS num FROM student GROUP BY class_id ORDER BY num DESC;
4. 限制结果(LIMIT)
sql
-- 查询前5条数据
SELECT * FROM student LIMIT 5;
-- 分页查询(第3页,每页10条:偏移量=10*(3-1)=20)
SELECT * FROM student LIMIT 20, 10;
-- MySQL 8.0+ 分页语法(更易读)
SELECT * FROM student LIMIT 10 OFFSET 20; -- 等价于LIMIT 20,10
5. 聚合查询(GROUP BY + 聚合函数)
常用聚合函数:
| 函数 | 示例 | 讲解 |
|---|---|---|
| COUNT() | COUNT(*)(统计行数)、COUNT(phone)(统计非空手机号) |
统计数量,COUNT(*)包含NULL,COUNT(字段)不包含NULL |
| SUM() | SUM(score) |
求和,仅数值型字段 |
| AVG() | AVG(score) |
求平均值,仅数值型字段 |
| MAX()/MIN() | MAX(score)/MIN(score) |
求最大/最小值 |
示例:
sql
-- 按班级分组,统计每个班级的学生数、平均年龄
SELECT class_id, COUNT(*) AS 学生数, AVG(age) AS 平均年龄
FROM student
GROUP BY class_id;
-- 按学生分组,计算每个学生的总分、最高分、最低分
SELECT s.name, SUM(sc.score) AS 总分, MAX(sc.score) AS 最高分, MIN(sc.score) AS 最低分
FROM student s
JOIN score sc ON s.id = sc.student_id
GROUP BY s.id, s.name;
-- HAVING过滤分组结果:筛选总分≥200的学生
SELECT s.name, SUM(sc.score) AS 总分
FROM student s
JOIN score sc ON s.id = sc.student_id
GROUP BY s.id, s.name
HAVING 总分 >= 200;
6. 连接查询(多表关联)
| 连接类型 | 示例 | 讲解 |
|---|---|---|
| INNER JOIN(内连接) | SELECT s.name, sc.score FROM student s INNER JOIN score sc ON s.id = sc.student_id; |
只返回两表匹配的行(默认JOIN就是内连接) |
| LEFT JOIN(左连接) | SELECT s.name, sc.score FROM student s LEFT JOIN score sc ON s.id = sc.student_id; |
返回左表(student)所有行,右表无匹配则为NULL |
| RIGHT JOIN(右连接) | SELECT s.name, sc.score FROM student s RIGHT JOIN score sc ON s.id = sc.student_id; |
返回右表(score)所有行,左表无匹配则为NULL |
| CROSS JOIN(笛卡尔积) | SELECT s.name, c.class_name FROM student s CROSS JOIN class c; |
两表所有行组合(无关联条件,慎用,数据量=行数1*行数2) |
7. 子查询(嵌套查询)
子查询是"查询中的查询",按结果类型分3类:
| 子查询类型 | 示例 | 讲解 |
|---|---|---|
| 标量子查询(单值) | SELECT name FROM student WHERE id = (SELECT student_id FROM score WHERE score = MAX(score)); |
结果是单个值,用=/>/<等运算符 |
| 列子查询(单列多行) | SELECT name FROM student WHERE id IN (SELECT student_id FROM score WHERE subject = '数学'); |
结果是单列多行,用IN/ANY/ALL等运算符 |
| 表子查询(多列多行) | SELECT * FROM (SELECT name, age FROM student WHERE class_id=1) AS t WHERE age > 18; |
结果是多列多行,需给子查询起别名(如t),当作临时表使用 |
8. 常用查询扩展
sql
-- 去重+统计:统计有多少个不同的班级
SELECT COUNT(DISTINCT class_id) FROM student;
-- 空值处理:用IFNULL替换NULL(无成绩显示0)
SELECT s.name, IFNULL(sc.score, 0) AS 成绩
FROM student s LEFT JOIN score sc ON s.id = sc.student_id;
-- 条件判断(CASE WHEN):按分数分级
SELECT name, subject, score,
CASE
WHEN score >= 90 THEN '优秀'
WHEN score >= 80 THEN '良好'
WHEN score >= 60 THEN '及格'
ELSE '不及格'
END AS 等级
FROM score;
四、DCL(数据控制语言):权限管理
用于管理MySQL用户和权限,仅管理员(root)可操作,核心语句:CREATE USER/GRANT/REVOKE。
1. 用户管理
sql
-- 创建用户(指定主机+密码)
-- 主机:%(任意主机)、localhost(仅本地)、192.168.1.%(指定网段)
CREATE USER IF NOT EXISTS 'dev'@'%' IDENTIFIED BY 'Dev@123456';
-- 修改用户密码
ALTER USER 'dev'@'%' IDENTIFIED BY 'NewDev@123456';
-- 重命名用户
RENAME USER 'dev'@'%' TO 'developer'@'%';
-- 删除用户
DROP USER IF EXISTS 'dev'@'%';
-- 查看所有用户
SELECT user, host FROM mysql.user;
2. 权限管理
| 操作 | 示例 | 讲解 |
|---|---|---|
| 授权 | GRANT SELECT, INSERT, UPDATE ON school_db.* TO 'developer'@'%'; |
授予school_db库所有表的查询/插入/更新权限;ALL PRIVILEGES是所有权限 |
| 授权(仅单表) | GRANT DELETE ON school_db.score TO 'developer'@'%'; |
仅授予score表的删除权限 |
| 授权(全局) | GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost'; |
授予所有数据库的所有权限(超级管理员) |
| 撤销权限 | REVOKE DELETE ON school_db.score FROM 'developer'@'%'; |
撤销指定权限 |
| 刷新权限 | FLUSH PRIVILEGES; |
授权/撤销后需执行,使权限生效 |
| 查看用户权限 | SHOW GRANTS FOR 'developer'@'%'; |
查看指定用户的权限 |
五、TCL(事务控制语言):事务管理
仅InnoDB引擎支持,核心语句:START TRANSACTION/COMMIT/ROLLBACK/SAVEPOINT。
sql
-- 1. 开启事务(关闭自动提交)
START TRANSACTION; -- 或 BEGIN;
-- 2. 执行DML操作
INSERT INTO student(name, age, class_id) VALUES('孙八', 20, 1);
UPDATE score SET score = 90 WHERE student_id = LAST_INSERT_ID(); -- LAST_INSERT_ID()获取刚插入的自增ID
-- 3. 创建保存点(可选)
SAVEPOINT sp1;
-- 4. 执行更多操作
DELETE FROM student WHERE name = '孙八';
-- 5. 回滚到保存点(孙八不会被删除)
ROLLBACK TO sp1;
-- 6. 提交事务(永久生效)
COMMIT;
-- 或回滚所有操作(撤销所有DML)
-- ROLLBACK;
-- 查看自动提交状态(默认ON)
SELECT @@AUTOCOMMIT;
-- 关闭自动提交(当前会话有效)
SET AUTOCOMMIT = OFF;
六、MySQL常用扩展语句
1. 注释
sql
-- 单行注释(最常用)
/*
多行注释
可写多行内容
*/
# 单行注释(类Shell风格,不推荐)
2. 变量与函数
sql
-- 定义用户变量
SET @stu_id = 1;
-- 使用变量查询
SELECT * FROM student WHERE id = @stu_id;
-- 常用系统函数
SELECT NOW(); -- 当前时间
SELECT DATE(NOW()); -- 仅日期
SELECT CONCAT(name, '-', class_id) FROM student; -- 字符串拼接
SELECT LENGTH(name); -- 字符串长度
SELECT YEAR(create_time) FROM student; -- 提取年份
3. 导入/导出数据
bash
# 导出数据库(终端执行)
mysqldump -u root -p school_db > school_db_backup.sql
# 导入数据库(终端执行)
mysql -u root -p school_db < school_db_backup.sql
- 基础知识点核心:InnoDB是唯一推荐的存储引擎(支持事务/外键);常用数据类型要匹配业务场景(如年龄用TINYINT UNSIGNED);约束是保证数据完整性的关键(主键/外键/非空/唯一)。
- SQL语句核心 :
- DDL操作结构(CREATE/ALTER/DROP),不可逆;
- DML操作数据(INSERT/UPDATE/DELETE),必须加WHERE(除批量操作);
- DQL是核心(SELECT),掌握JOIN/分组/子查询可解决90%查询需求;
- TCL仅InnoDB支持,事务保证数据操作的原子性。
- 避坑:禁用SELECT *;UPDATE/DELETE必加WHERE;索引按需添加(不滥用);事务操作后记得COMMIT/ROLLBACK。