[数据库] MySQL 数据库核心知识点全整理:SQL 语句规范、实战与避坑指南

86 0
Honkers 3 小时前 来自手机 | 显示全部楼层 |阅读模式

MySQL 数据库技术核心知识点全整理:SQL 语句规范、实战与避坑指南

📑 文章目录

  • 一、DDL 语句:库、表、索引创建/修改/删除
  • 二、DML 语句:增删改查数据操作
  • 三、DQL 查询语句:SELECT 核心查询逻辑
  • 四、DCL 权限管理:用户创建、授权、回收
  • 五、视图与索引原理、实战场景
  • 六、事务管理 ACID 四大特性与实操
  • 七、MySQL 作业高频报错 TOP10(个人实战踩坑汇总)
  • 八、综合实战案例:schooldb 教学库完整多条件查询
  • 九、学习心得总结

前言

最开始接触 MySQL 时,我觉得只是写简单增删改查,直到作业里频繁爆出各种报错:改密码语法失效、授权后用户无法登录、删表误删全库、UPDATE 漏 WHERE 清空整张表、事务自动提交导致回滚失效……踩坑无数后,我把 DDL/DML/DQL/DCL、索引视图、事务原理、高频报错解决方案全部系统整理,搭配课堂 schooldb 教学库实战代码,兼顾理论、实操与排错,适合数据库入门复习与作业参考。

📌 SQL 语言四大分类(按功能划分)

掌握 SQL,首先要理解其语句的四大功能分类。它们各司其职,共同构成了完整的数据管理体系:

  • DDL (数据定义语言) - 定义结构

    • 功能:定义和修改数据库、表、索引等结构
    • 核心语句:CREATE, ALTER, DROP, TRUNCATE。
    • 操作对象:数据库元数据。
    • 特点:通常自动提交,不可回滚,操作需谨慎。
  • DML (数据操作语言) - 操作数据

    • 功能:对表中的数据进行增、删、改。
    • 核心语句:INSERT, UPDATE, DELETE。
    • 操作对象:表内的业务数据。
    • 特点:需显式提交或回滚,是业务操作最频繁的部分。
  • DQL (数据查询语言) - 查询数据

    • 功能:从数据库中检索数据,是使用频率最高的部分。
    • 核心语句:SELECT,及其搭配的 WHERE, JOIN, GROUP BY, ORDER BY 等子句。
    • 操作对象:数据。
    • 特点:不会修改数据,但查询逻辑可以非常复杂。
  • DCL (数据控制语言) - 控制权限

    • 功能:管理数据库用户的访问权限和安全
    • 核心语句:GRANT, REVOKE, CREATE USER, ALTER USER。
    • 操作对象:用户和权限。
    • 特点:通常由数据库管理员(DBA)执行。

提示:下文将按照 DDL → DML → DQL → DCL 的顺序,结合 schooldb 教学库的实战代码,详细讲解每类语句的语法、实战案例及我踩过的坑。

一、DDL 语句:库、表、索引创建/修改/删除

DDL(数据定义语言)负责数据库、数据表、索引、字段结构的定义,操作直接修改元数据,风险极高,是我作业报错最多的模块之一。

1.1 数据库库级操作

创建数据库

  1. CREATE DATABASE IF NOT EXISTS schooldb DEFAULT CHARACTER SET utf8mb4;
复制代码

踩坑记录:初次写代码省略 IF NOT EXISTS,重复执行建库语句直接报 Can't create database 'schooldb'; database exists,每次运行脚本都中断。

修改数据库字符集

  1. ALTER DATABASE schooldb CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
复制代码

删除数据库

  1. DROP DATABASE IF EXISTS schooldb;
复制代码

1.2 数据表操作

创建表(课堂学生表示例)

  1. CREATE TABLE IF NOT EXISTS student (
  2. id INT PRIMARY KEY AUTO_INCREMENT COMMENT '学生编号',
  3. name VARCHAR(20) NOT NULL COMMENT '学生姓名',
  4. class_id INT COMMENT '班级编号',
  5. age TINYINT COMMENT '学生年龄'
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
复制代码

修改表结构 ALTER TABLE

新增字段

  1. ALTER TABLE student ADD COLUMN gender CHAR(1) COMMENT '性别';
复制代码

修改字段类型/约束(MODIFY,只写一次字段名)

  1. ALTER TABLE student MODIFY age TINYINT UNSIGNED;
复制代码

修改字段名称 + 类型(CHANGE,必须写旧名 + 新名)

  1. ALTER TABLE student CHANGE gender sex CHAR(1) COMMENT '性别';
复制代码

踩坑记录:第一次修改字段名混用 MODIFY 语法,只写新字段名,持续报 You have an error in your SQL syntax,反复核对文档才分清 MODIFY 与 CHANGE 区别。

删除字段

  1. ALTER TABLE student DROP COLUMN sex;
复制代码

清空/删除表

  1. -- 清空表数据,保留表结构
  2. TRUNCATE TABLE student;
  3. -- 直接删除整张表
  4. DROP TABLE IF EXISTS student;
复制代码

踩坑记录:作业中误将 DROP 代替 TRUNCATE,写完测试数据后表直接消失,只能重新建表导入测试数据。

1.3 索引 DDL 操作

创建普通索引

  1. CREATE INDEX idx_stu_class_id ON student(class_id);
复制代码

删除索引

  1. DROP INDEX idx_stu_class_id ON student;
复制代码

二、DML 语句:增删改查数据操作

DML(数据操作语言)操作表内业务数据,日常使用频率最高,也是最容易误操作丢失数据的模块。

2.1 INSERT 插入数据

单条插入

  1. INSERT INTO student(name, class_id, age) VALUES ('张三', 1, 18);
复制代码

批量插入(推荐,单次 IO,性能远高于多条 INSERT)

  1. INSERT INTO student(name, class_id, age)
  2. VALUES
  3. ('李四', 1, 17),
  4. ('王五', 2, 19),
  5. ('赵六', 2, 18);
复制代码

踩坑记录:批量插入时字段值数量和前面字段列表不匹配,报 Column count doesn't match value count at row x。

2.2 UPDATE 修改数据(最高危 SQL)

  1. UPDATE student SET age = 18 WHERE id = 1;
复制代码

踩坑血泪史:第一次写作业忘记加 WHERE,整张学生表年龄全部统一修改,没有备份只能重新导入测试数据,之后养成先 SELECT 校验条件再 UPDATE 的习惯。

2.3 DELETE 删除数据

  1. DELETE FROM student WHERE id = 1;
复制代码

区分:DELETE 是 DML,会记录事务日志,可回滚;TRUNCATE 属于 DDL,无日志、不可回滚。

三、DQL 查询语句:SELECT 核心查询逻辑

DQL 是数据库使用核心,多表联查、分组过滤、子查询是考试与作业高频考点。

3.1 基础查询、条件过滤 WHERE

  1. SELECT id, name, age FROM student WHERE age >= 18;
复制代码

3.2 多表 JOIN 联表查询

INNER JOIN 内连接:只返回两张表匹配成功的数据

  1. SELECT s.name, c.class_name
  2. FROM student s
  3. INNER JOIN class c ON s.class_id = c.id;
复制代码

LEFT JOIN 左连接:左表所有数据保留,右表无匹配填充 NULL

  1. SELECT s.name, c.class_name
  2. FROM student s
  3. LEFT JOIN class c ON s.class_id = c.id;
复制代码

踩坑记录:混淆 LEFT JOIN 与 INNER JOIN,需求需要展示全部学生却使用内连接,丢失无班级的学生数据,查询结果不符合业务需求。

3.3 分组 GROUP BY + HAVING

  • WHERE:分组前过滤原始数据,不能使用聚合函数
  • HAVING:分组后过滤分组结果,仅配合 GROUP BY 使用,支持 SUM/COUNT 等聚合函数
  1. SELECT class_id, COUNT(*) AS stu_num, AVG(age) AS avg_age
  2. FROM student
  3. WHERE age > 17
  4. GROUP BY class_id
  5. HAVING COUNT(*) >= 2;
复制代码

踩坑记录:把 COUNT() 聚合条件写在 WHERE 中,直接报 Invalid use of group function。

3.4 子查询 IN / EXISTS

  • IN:子查询数据量小时适用,先执行子查询再匹配
  • EXISTS:数据量大性能更优,外部表逐行匹配,找到匹配项立刻终止
  1. -- IN 子查询示例
  2. SELECT * FROM student WHERE class_id IN (SELECT id FROM class);
复制代码

拓展知识点(课堂未重点讲解):窗口函数

老师课堂仅讲解基础聚合分组,我查阅官方文档补充窗口函数 ROW_NUMBER(),用于分组内排序:

  1. SELECT *,
  2. ROW_NUMBER() OVER(PARTITION BY class_id ORDER BY age DESC) AS rank_num
  3. FROM student;
复制代码

四、DCL 权限管理:用户创建、授权、回收

对应课堂 schooldb 用户权限作业,包含创建用户、改密码、授权、回收权限完整代码,也是本次连线题核心知识点。

4.1 创建数据库用户

  1. CREATE USER 'general'@'localhost' IDENTIFIED BY '123456';
  2. CREATE USER 'admin'@'localhost' IDENTIFIED BY 'admin123';
复制代码

踩坑记录:创建用户后授权语句执行正常,但本地登录失败,排查发现用户后缀缺少 @localhost,默认 % 远程用户,本地登录不匹配。

4.2 修改用户密码

旧版本 SET PASSWORD 语法已逐步废弃,新版本推荐 ALTER USER 标准语法。

  1. ALTER USER 'general'@'localhost' IDENTIFIED BY '654321';
复制代码

4.3 GRANT 授予权限

普通用户 general:仅查询 course 单表

  1. GRANT SELECT ON schooldb.course TO 'general'@'localhost';
复制代码

管理员 admin:schooldb 全表增删改查全部权限

  1. GRANT SELECT, INSERT, UPDATE, DELETE ON schooldb.* TO 'admin'@'localhost';
复制代码

4.4 REVOKE 回收权限

  1. REVOKE SELECT ON schooldb.course FROM 'general'@'localhost';
复制代码

踩坑记录:回收权限时库名、表名写错,执行无报错但权限未生效,核对表名后正常。

  1. -- 查看admin用户拥有的权限
  2. SHOW GRANTS FOR 'admin'@'localhost';
复制代码

五、视图与索引原理、实战场景

5.1 视图 VIEW

视图是虚拟查询表,存储查询语句,不占用物理存储,简化复杂联查。

  1. CREATE VIEW v_stu_class AS
  2. SELECT s.id, s.name, c.class_name
  3. FROM student s
  4. LEFT JOIN class c ON s.class_id = c.id;
复制代码

注意:视图仅简化查询,不提升查询性能,频繁更新的业务不建议大量使用视图。

5.2 索引原理与使用场景

索引底层 InnoDB 使用 B+树,大幅提升 WHERE、JOIN 查询速度,但会降低 INSERT/UPDATE/DELETE 写入性能。

适用场景:经常作为查询条件、关联条件的字段(班级 id、学生 id)

不适合:频繁修改、重复度极高字段(性别、状态)

  1. CREATE INDEX idx_stu_name ON student(name);
复制代码

踩坑记录:给低区分度字段(性别)创建索引,查询完全没有提速,反而拖慢写入速度。

六、事务管理 ACID 四大特性与实操

6.1 事务四大核心特性 ACID

  • A (Atomicity) 原子性:事务不可分割,全部执行成功或全部回滚
  • C (Consistency) 一致性:事务前后业务数据逻辑合法
  • I (Isolation) 隔离性:并发事务互不干扰,依靠锁、MVCC 实现
  • D (Durability) 持久性:提交后数据永久落地,宕机不丢失

6.2 事务基础语法

MySQL InnoDB 引擎支持事务,默认自动提交 autocommit=1,手动事务需关闭自动提交。

  1. -- 关闭自动提交
  2. SET autocommit = 0;
  3. -- 开启事务
  4. START TRANSACTION;
  5. -- 执行SQL操作
  6. UPDATE account SET balance = balance - 100 WHERE id = 1;
  7. UPDATE account SET balance = balance + 100 WHERE id = 2;
  8. -- 提交事务
  9. COMMIT;
  10. -- 回滚事务(出错时执行)
  11. -- ROLLBACK;
复制代码

6.3 保存点局部回滚 SAVEPOINT

  1. START TRANSACTION;
  2. SAVEPOINT point1;
  3. UPDATE account SET balance = 800 WHERE id = 1;
  4. -- 回滚到指定保存点
  5. ROLLBACK TO point1;
  6. COMMIT;
复制代码

踩坑记录:忘记关闭 autocommit,执行 UPDATE 后自动提交,ROLLBACK 完全失效,转账模拟案例数据错乱。

6.4 并发事务三大隔离问题

  • 脏读:读取其他事务未提交的临时数据,对方回滚后数据失效
  • 不可重复读:同一事务两次读取,中间被其他事务 UPDATE 提交,数值变化
  • 幻读:同一事务两次统计行数,中间被其他事务 INSERT/DELETE,总数增减

脏读模拟(需设置隔离级别为 READ UNCOMMITTED)

  1. -- 会话1:开启事务,修改数据但不提交
  2. SET autocommit = 0;
  3. SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
  4. UPDATE account SET balance = 900 WHERE id = 1;
  5. -- 会话2:查询到未提交数据(脏读)
  6. SELECT * FROM account WHERE id = 1; -- 读到900,但会话1可能回滚
复制代码

七、MySQL 作业高频报错 TOP10(个人实战踩坑汇总)

📌 此处插入作业 SQL 报错案例(如 Navicat 命令行报错弹窗)

在 MySQL 学习和作业实践中,报错信息是帮助我们理解 SQL 语法的“老师”。下面我将自己踩过的十大高频报错,按照 DDL、DML、DQL、DCL、事务 五大类别进行梳理,并附上最直接的解决方案,帮你一眼看懂问题所在,快速定位修复。

7.1 DDL(数据定义)相关报错

这类错误通常发生在创建、修改数据库或表结构时。

报错信息出错原因解决方案
Can’t create database ‘schooldb’; database exists重复执行 CREATE DATABASE 建库语句。在 CREATE DATABASE 后加上 IF NOT EXISTS 子句。
You have an error in your SQL syntax修改表结构时语法错误,常见于混淆 MODIFY 和 CHANGE。修改字段类型/约束用 MODIFY修改字段名用 CHANGE(必须写旧名+新名)。检查逗号、引号等标点。

7.2 DML(数据操作)相关报错

这类错误发生在对数据进行增、删、改操作时,是数据丢失的“重灾区”。

报错信息出错原因解决方案
Column count doesn’t match value count at row xINSERT 语句中,字段列表的数量与 VALUES 括号内的数据个数不匹配。逐行核对 INSERT INTO table (col1, col2, ...) 与 VALUES (val1, val2, ...) 的数量是否一致。
UPDATE 全表数据无过滤执行 UPDATE 语句时,忘记写 WHERE 条件,导致整张表的数据被意外修改。高危操作习惯:修改前先用 SELECT ... WHERE ... 验证条件是否能精确锁定目标行。
DELETE 与 TRUNCATE 混淆误用 DROP TABLE 或 TRUNCATE TABLE 来删除部分数据,导致表被清空或删除。DELETE:删除指定行(DML,可回滚)。TRUNCATE:清空整表(DDL,不可回滚)。明确需求再选择。

7.3 DQL(数据查询)相关报错

这类错误多出现在复杂的查询语句中,尤其是涉及聚合和联表时。

报错信息出错原因解决方案
Invalid use of group function在 WHERE 子句中使用了聚合函数(如 COUNT(), SUM())。聚合函数的过滤条件必须写在 HAVING 子句中。WHERE 仅用于分组前的原始数据过滤。
Left JOIN 丢失左表数据在使用 LEFT JOIN 时,将右表的过滤条件错误地放在了 WHERE 子句中。右表的过滤条件应放在 ON 子句后(如 ON c.id = s.class_id AND c.status=1),WHERE 只过滤左表。
Index doesn‘t speed up query在区分度极低的字段(如“性别”)上创建了索引,导致索引失效。只为高频查询区分度高的字段(如学号、用户名)创建索引。对低区分度字段建索引弊大于利。

7.4 DCL(权限控制)相关报错

这类错误与用户、权限管理相关,常导致“登录失败”或“操作被拒绝”。

报错信息出错原因解决方案
Access denied for user ‘xxx’@‘localhost’用户不存在、密码错误,或用户的主机名(如 @localhost 与 @%)不匹配。1. 确认用户已创建:CREATE USER 'xxx'@'localhost' IDENTIFIED BY '密码';
2. 确认已授权:GRANT ... TO 'xxx'@'localhost';
3. 核对连接时使用的主机名。
Revoke 执行无效果执行 REVOKE 回收权限时,库名、表名或用户名书写错误,与授权时的对象不匹配。使用 SHOW GRANTS FOR 'user'@'host'; 查看用户现有权限,确保 REVOKE 语句中的对象名称与之一致。

7.5 事务相关报错

这类错误与事务的开启、提交、回滚机制有关。

报错信息出错原因解决方案
ROLLBACK 无效,数据已保存MySQL 默认 autocommit=1(自动提交),执行 UPDATE 后数据立即持久化,ROLLBACK 无法撤销。在需要手动控制事务时,先执行 SET autocommit = 0; 关闭自动提交,再使用 START TRANSACTION;。

总结与避坑心法

  1. DDL 操作前先备份:结构变更风险高,操作前务必确认环境。
  2. DML 操作先 SELECT:执行 UPDATE、DELETE 前,先用 SELECT 带上相同 WHERE 条件预览要操作的数据。
  3. 权限问题看 GRANTS:遇到权限错误,第一时间用 SHOW GRANTS 检查。
  4. 事务操作关自动提交:进行转账、批量更新等关键操作时,记得 SET autocommit=0。

把这张表存下来,下次遇到报错先来这里对照,能帮你节省大量排查时间!

八、综合实战案例:schooldb 教学库完整多条件查询

需求:查询每个班级学生人数、平均分,仅展示平均分大于 80 的班级,展示班级名称、人数、平均分,包含无成绩学生。

  1. SELECT
  2. c.class_name,
  3. COUNT(s.id) AS stu_count,
  4. ROUND(AVG(sc.score), 2) AS avg_score
  5. FROM class c
  6. LEFT JOIN student s ON c.id = s.class_id
  7. LEFT JOIN score sc ON s.id = sc.stu_id
  8. WHERE s.age > 17
  9. GROUP BY c.id, c.class_name
  10. HAVING AVG(sc.score) > 80
  11. ORDER BY avg_score DESC;
复制代码

代码解析

  • 左连接班级、学生、成绩表,保留无成绩学生
  • WHERE 过滤 17 岁以上学生
  • GROUP BY 按班级分组统计
  • HAVING 过滤平均分 80 以上班级
  • ROUND 保留两位小数,ORDER BY 平均分倒序

九、学习心得总结

最开始接触 MySQL 时,我简单认为只是写增删改查,完成课堂连线、备份、权限作业时接连踩坑:改密码语法错误、授权后用户登录失败、漏写 WHERE 全表更新、事务自动提交无法回滚。梳理知识点后才意识到 MySQL 是一套完整的数据管理体系:DDL 管控结构、DML 操作数据、DCL 管控访问权限、事务保障数据安全,索引与视图优化查询效率。

很多课堂只浅讲基础语法,但实操报错才能真正理解底层逻辑,比如 INNER 与 LEFT JOIN 的区别、WHERE 与 HAVING 的过滤时机、TRUNCATE 与 DELETE 的事务差异。后续学习我会重点深耕索引优化、事务隔离级别、慢查询调优,把本次整理的避坑清单作为日常开发自查标准,避免重复踩相同错

💡 给初学者的后续学习建议

学完前面的内容,你已经掌握了 MySQL 的基础操作和常见避坑技巧。如果还想继续深入,可以从下面几个方向入手:

1. 索引优化:从看懂 EXPLAIN 开始

你已经知道索引是 B+树结构,但怎么知道自己的 SQL 有没有用上索引呢?用 EXPLAIN 命令!

  1. -- 在 SQL 语句前加上 EXPLAIN
  2. EXPLAIN SELECT * FROM student WHERE name = '张三';
复制代码

执行后会看到一张表,重点关注这几列:

  • type:如果是 ALL(全表扫描)就要小心了,说明没用到索引
  • key:显示实际使用的索引名
  • rows:预估要扫描的行数,越少越好

小练习:给 student 表的 name 字段建索引后,再执行上面的 EXPLAIN,看看结果有什么变化?

2. 事务隔离级别:先理解概念,再动手实验

MySQL 默认使用 REPEATABLE READ(可重复读),但很多项目会用 READ COMMITTED(读已提交)。两者的主要区别:

  • REPEATABLE READ:同一个事务内,多次读取同一数据结果一致(像拍了张快照)
  • READ COMMITTED:能读到其他事务已提交的修改(更接近现实世界)

怎么选?

  • 如果业务要求数据绝对一致(如银行余额),用 REPEATABLE READ
  • 如果追求更高并发性能,能接受读到最新提交的数据,用 READ COMMITTED

动手实验(用两个命令行窗口):

  1. 窗口1:SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
  2. 窗口1:开启事务并修改数据但不提交
  3. 窗口2:查询同一数据,看看能读到什么

3. 窗口函数:ROW_NUMBER、RANK、DENSE_RANK 的区别

窗口函数能让分组排序更灵活,三者的区别用一个例子就明白了:

假设班级成绩表:

  1. 姓名 分数
  2. 张三 95
  3. 李四 90
  4. 王五 90
  5. 赵六 85
复制代码
  1. SELECT
  2. 姓名,
  3. 分数,
  4. ROW_NUMBER() OVER(ORDER BY 分数 DESC) as row_num,
  5. RANK() OVER(ORDER BY 分数 DESC) as rank_num,
  6. DENSE_RANK() OVER(ORDER BY 分数 DESC) as dense_rank_num
  7. FROM 成绩表;
复制代码

结果:

  1. 姓名 分数 row_num rank_num dense_rank_num
  2. 张三 95 1 1 1
  3. 李四 90 2 2 2
  4. 王五 90 3 2 2
  5. 赵六 85 4 4 3
复制代码

简单记

  • ROW_NUMBER():永远连续编号(1,2,3,4…)
  • RANK():并列会跳号(1,2,2,4…)
  • DENSE_RANK():并列不跳号(1,2,2,3…)

📚 下一步学习路线建议

  1. 先巩固:把本文的代码都在自己的 MySQL 里跑一遍,确保每个报错都亲手遇到过
  2. 再拓展:找一些简单的学生管理系统项目练手,把增删改查、联表查询都用上
  3. 后深入:等熟练了再研究执行计划、事务隔离、窗口函数这些高级特性

记住:数据库学习是循序渐进的,先把基础打牢,后面的高级特性自然就理解了。加油!💪

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2026 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行