MySQL基础知识点与常用SQL语句整理

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 > 18score <> 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

  1. 基础知识点核心:InnoDB是唯一推荐的存储引擎(支持事务/外键);常用数据类型要匹配业务场景(如年龄用TINYINT UNSIGNED);约束是保证数据完整性的关键(主键/外键/非空/唯一)。
  2. SQL语句核心
    • DDL操作结构(CREATE/ALTER/DROP),不可逆;
    • DML操作数据(INSERT/UPDATE/DELETE),必须加WHERE(除批量操作);
    • DQL是核心(SELECT),掌握JOIN/分组/子查询可解决90%查询需求;
    • TCL仅InnoDB支持,事务保证数据操作的原子性。
  3. 避坑:禁用SELECT *;UPDATE/DELETE必加WHERE;索引按需添加(不滥用);事务操作后记得COMMIT/ROLLBACK。
相关推荐
青衫码上行2 小时前
高频SQL 50题 | 聚合
数据库·sql·mysql·leetcode·面试
有点心急10212 小时前
SQL 执行 MCP 工具开发(二)
数据库·sql
m0_528749002 小时前
复杂一点的sql查询
数据库·sql
XiaoLeisj2 小时前
Android RecyclerView 实战:从基础列表到多类型 Item、分割线与状态复用问题
android·java
崎岖Qiu2 小时前
使用 Redis 的 List 实现缓存分页信息(模拟 limit offset 的 SQL 语句)
redis·mysql·缓存·list
zh_xuan2 小时前
kotlin async异步协程构建器
android·kotlin·协程
阿林来了2 小时前
Flutter三方库适配OpenHarmony【flutter_web_auth】— Android 端 Chrome Custom Tabs 实现分析
android·chrome·flutter
zh_xuan4 小时前
kotlin Channel的用法
android·kotlin·协程·channel
zh_xuan4 小时前
kotlin Flow的用法
android·开发语言·kotlin·协程·flow