一、命名约定与占位符说明
| 占位符 |
含义 |
表1 / 表2 |
任意表名(表1 为左表/驱动表,表2 为右表/被驱动表) |
主表 / 从表 |
具有主外键关系的两张表(主表 为父表,从表 为子表) |
字段1 / 字段2 |
表中的列名 |
值1 / 值2 |
要插入/更新的具体值 |
条件 |
WHERE 子句中的过滤表达式 |
别名 |
表或列的临时别名(AS 关键字可选) |
二、DDL — 数据定义语言
DDL 用于定义和管理数据库对象的结构(库、表、索引、视图等),操作自动提交且不可回滚。
2.1 数据库操作
2.1.1 查看数据库
-- 查看所有数据库
SHOW DATABASES;
-- 查看当前使用的数据库
SELECT DATABASE();
-- 查看创建某个数据库的完整SQL
SHOW CREATE DATABASE 数据库名;
2.1.2 创建数据库
-- 最简创建
CREATE DATABASE 数据库名;
-- 完整语法(推荐)
CREATE DATABASE [IF NOT EXISTS] 数据库名
[DEFAULT] CHARACTER SET [=] 字符集名 -- 默认 utf8mb4
[DEFAULT] COLLATE [=] 排序规则名; -- 默认 utf8mb4_general_ci
| 参数 |
说明 |
IF NOT EXISTS |
仅当库不存在时才创建,避免报错 |
CHARACTER SET / CHARSET |
指定字符集(推荐 utf8mb4,支持 emoji) |
COLLATE |
指定排序规则(_ci 大小写不敏感,_cs 大小写敏感,_bin 二进制比较) |
示例:
CREATE DATABASE IF NOT EXISTS mydb
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_unicode_ci;
2.1.3 修改 & 删除数据库
-- 修改数据库属性(只能改字符集/排序规则)
ALTER DATABASE 数据库名
[DEFAULT] CHARACTER SET utf8mb4
[DEFAULT] COLLATE utf8mb4_general_ci;
-- 删除数据库(不可逆!)
DROP DATABASE [IF EXISTS] 数据库名;
-- 切换当前数据库
USE 数据库名;
2.2 表操作 — 创建表 (CREATE TABLE)
2.2.1 基础建表(初级)
CREATE TABLE [IF NOT EXISTS] 表1 (
-- 自动增长主键
id INT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
-- 定长字符串(长度固定,不足补空格,最大 255)
字段1 CHAR(10) NOT NULL COMMENT '定长字段',
-- 变长字符串(按实际长度存储,最大 65535)
字段2 VARCHAR(50) DEFAULT '默认值' COMMENT '变长字段',
-- 整数类型
字段3 INT DEFAULT 0 COMMENT '整数',
-- 小数(总共 M 位,小数 D 位)
字段4 DECIMAL(10,2) COMMENT '精确小数',
-- 日期时间
字段5 DATE COMMENT '日期',
字段6 TIME COMMENT '时间',
字段7 DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '日期时间',
-- 枚举(只能取列表中的值)
字段8 ENUM('值1','值2','值3') DEFAULT '值1' COMMENT '枚举',
-- 文本
字段9 TEXT COMMENT '长文本',
-- 布尔(实际是 TINYINT(1))
字段10 BOOLEAN DEFAULT TRUE COMMENT '布尔'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='表注释';
2.2.2 数据类型速查
数值类型:
| 类型 |
字节 |
有符号范围 |
无符号范围 |
说明 |
TINYINT |
1 |
-128 ~ 127 |
0 ~ 255 |
微整数 |
SMALLINT |
2 |
-32768 ~ 32767 |
0 ~ 65535 |
小整数 |
MEDIUMINT |
3 |
-838万 ~ 838万 |
0 ~ 1677万 |
中整数 |
INT / INTEGER |
4 |
-21亿 ~ 21亿 |
0 ~ 42亿 |
整数 |
BIGINT |
8 |
-9e18 ~ 9e18 |
0 ~ 1.8e19 |
大整数 |
FLOAT(M,D) |
4 |
— |
— |
单精度浮点(不精确) |
DOUBLE(M,D) |
8 |
— |
— |
双精度浮点(不精确) |
DECIMAL(M,D) |
变长 |
— |
— |
定点精确小数(金融计算推荐) |
UNSIGNED 关键字可将整数列设为无符号,范围翻倍。
字符串类型:
| 类型 |
最大长度 |
说明 |
CHAR(N) |
255 |
定长,存储时右侧补空格,读取时去空格 |
VARCHAR(N) |
65535 |
变长,额外 1~2 字节存长度 |
TINYTEXT |
255 |
微文本 |
TEXT |
65535 |
长文本 |
MEDIUMTEXT |
16777215 |
中文本 |
LONGTEXT |
4294967295 |
超长文本 |
BLOB 系列 |
同上 |
二进制大对象(存图片/文件) |
ENUM('a','b') |
65535 个值 |
单选枚举 |
SET('a','b') |
64 个值 |
多选集合 |
JSON |
1GB |
JSON 文档(5.7.8+) |
日期时间类型:
| 类型 |
格式 |
范围 |
说明 |
DATE |
YYYY-MM-DD |
1000-01-01 ~ 9999-12-31 |
日期 |
TIME |
HH:MM:SS |
-838:59:59 ~ 838:59:59 |
时间/时长 |
DATETIME |
YYYY-MM-DD HH:MM:SS |
1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 |
日期时间 |
TIMESTAMP |
YYYY-MM-DD HH:MM:SS |
1970-01-01 00:00:01 UTC ~ 2038-01-19 |
时间戳(自动时区转换) |
YEAR |
YYYY |
1901 ~ 2155 |
年份 |
2.2.3 约束 (Constraints) — 中级
CREATE TABLE 主表 (
id INT AUTO_INCREMENT,
字段1 VARCHAR(50) NOT NULL, -- 非空约束
字段2 VARCHAR(100) UNIQUE, -- 唯一约束(允许 NULL)
字段3 INT DEFAULT 0, -- 默认值约束
字段4 CHAR(36) DEFAULT (UUID()), -- 默认值可以是表达式(8.0.13+)
-- 主键约束(等价于 NOT NULL + UNIQUE,每表只能有一个)
PRIMARY KEY (id),
-- 检查约束(8.0.16+ 强制执行)
CONSTRAINT chk_字段3 CHECK (字段3 >= 0 AND 字段3 <= 100),
-- 唯一约束(命名方式)
CONSTRAINT uk_字段1 UNIQUE (字段1)
) COMMENT '主表(父表)';
CREATE TABLE 从表 (
id INT AUTO_INCREMENT PRIMARY KEY,
主表_id INT NOT NULL,
字段1 VARCHAR(50),
-- 外键约束(引用主表的主键)
CONSTRAINT fk_从表_主表
FOREIGN KEY (主表_id) REFERENCES 主表(id)
ON DELETE CASCADE -- 主表删除时,从表相关行级联删除
ON UPDATE CASCADE -- 主表更新时,从表外键值级联更新
) COMMENT '从表(子表)';
外键级联策略(ON DELETE / ON UPDATE):
| 策略 |
说明 |
CASCADE |
级联:主表删/改,从表跟着删/改 |
SET NULL |
置空:主表删/改,从表外键列置为 NULL(要求该列允许 NULL) |
RESTRICT / NO ACTION |
禁止:如果从表还有引用,禁止主表删/改(默认行为) |
SET DEFAULT |
设为默认值(InnoDB 不支持此策略) |
建表约束定义位置的两种写法:
-- 方式一:列级约束(紧跟字段定义)
字段1 VARCHAR(50) NOT NULL UNIQUE
-- 方式二:表级约束(在所有列定义之后,可以命名、可以定义组合约束)
CONSTRAINT 约束名 PRIMARY KEY (字段1, 字段2)
2.2.4 索引 — 建表时创建
CREATE TABLE 表1 (
id INT,
字段1 VARCHAR(50),
字段2 INT,
字段3 VARCHAR(100),
-- 普通索引
INDEX idx_字段1 (字段1),
-- 唯一索引(索引列的值必须唯一,允许 NULL)
UNIQUE INDEX idx_字段2 (字段2),
-- 全文索引(仅 CHAR/VARCHAR/TEXT,InnoDB 6+ 支持)
FULLTEXT INDEX ft_idx_字段3 (字段3),
-- 复合索引(联合索引,注意最左前缀原则)
INDEX idx_复合 (字段1, 字段2),
-- 空间索引(仅 GEOMETRY 类型)
SPATIAL INDEX sp_idx (geo_column)
) ENGINE=InnoDB;
2.2.5 建表高级选项
CREATE TABLE 表1 (
-- ... 列定义 ...
) ENGINE=InnoDB
AUTO_INCREMENT=1000 -- 自增起始值
DEFAULT CHARSET=utf8mb4 -- 表级字符集
COLLATE=utf8mb4_unicode_ci -- 表级排序规则
COMMENT='表注释'
ROW_FORMAT=DYNAMIC -- 行格式(REDUNDANT/COMPACT/DYNAMIC/COMPRESSED)
KEY_BLOCK_SIZE=8 -- 索引块大小
TABLESPACE=表空间名 -- 指定表空间
PARTITION BY RANGE (字段2) ( -- 分区(高级)
PARTITION p0 VALUES LESS THAN (100),
PARTITION p1 VALUES LESS THAN (200),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
2.3 表操作 — 修改表 (ALTER TABLE)
2.3.1 列操作
-- 添加列
ALTER TABLE 表1
ADD [COLUMN] 字段1 VARCHAR(50) [FIRST | AFTER 已有列名];
-- 添加多列(逗号分隔,不能用 FIRST/AFTER)
ALTER TABLE 表1
ADD COLUMN (字段2 INT DEFAULT 0, 字段3 DATE);
-- 修改列定义(数据类型/默认值/注释)
ALTER TABLE 表1
MODIFY [COLUMN] 字段1 VARCHAR(100) NOT NULL DEFAULT 'new' COMMENT '新注释';
-- 重命名列 + 修改定义
ALTER TABLE 表1
CHANGE [COLUMN] 旧字段名 新字段名 VARCHAR(50) NOT NULL COMMENT '重命名';
-- 删除列
ALTER TABLE 表1
DROP [COLUMN] 字段1;
2.3.2 约束操作
-- 添加主键
ALTER TABLE 表1 ADD PRIMARY KEY (字段1);
-- 删除主键(AUTO_INCREMENT 列必须先 MODIFY 去掉自增属性)
ALTER TABLE 表1 DROP PRIMARY KEY;
-- 添加外键
ALTER TABLE 从表
ADD CONSTRAINT fk_从表_主表
FOREIGN KEY (主表_id) REFERENCES 主表(id)
ON DELETE CASCADE ON UPDATE CASCADE;
-- 删除外键(删外键约束名,不是删列)
ALTER TABLE 从表 DROP FOREIGN KEY fk_从表_主表;
-- 添加/删除唯一约束
ALTER TABLE 表1 ADD CONSTRAINT uk_字段1 UNIQUE (字段1);
ALTER TABLE 表1 DROP INDEX uk_字段1; -- 唯一约束当作索引删除
-- 添加/删除检查约束
ALTER TABLE 表1 ADD CONSTRAINT chk_字段1 CHECK (字段1 > 0);
ALTER TABLE 表1 DROP CHECK chk_字段1;
-- 修改默认值
ALTER TABLE 表1 ALTER [COLUMN] 字段1 SET DEFAULT 新默认值;
ALTER TABLE 表1 ALTER [COLUMN] 字段1 DROP DEFAULT;
2.3.3 索引操作
-- 创建索引
CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX 索引名
ON 表1 (字段1 [ASC|DESC], 字段2 [ASC|DESC]) -- ASC 默认
[USING BTREE | HASH]
[COMMENT '索引说明']
[VISIBLE | INVISIBLE]; -- 8.0+ 不可见索引
-- 通过 ALTER 方式创建
ALTER TABLE 表1 ADD INDEX idx_字段1 (字段1);
-- 删除索引
DROP INDEX 索引名 ON 表1;
ALTER TABLE 表1 DROP INDEX 索引名;
-- 查看表上所有索引
SHOW INDEX FROM 表1;
-- 重建/优化索引
ALTER TABLE 表1 ENGINE=InnoDB; -- 重建整表
OPTIMIZE TABLE 表1; -- 优化表(碎片整理+索引重建)
ANALYZE TABLE 表1; -- 更新索引统计信息
2.3.4 表级操作
-- 重命名表
RENAME TABLE 旧表名 TO 新表名;
ALTER TABLE 旧表名 RENAME [TO|AS] 新表名;
RENAME TABLE 表1 TO 新表1, 表2 TO 新表2; -- 原子重命名多表
-- 修改表注释
ALTER TABLE 表1 COMMENT = '新注释';
-- 修改存储引擎
ALTER TABLE 表1 ENGINE = MyISAM;
-- 修改自增值
ALTER TABLE 表1 AUTO_INCREMENT = 10000;
-- 修改字符集/排序规则
ALTER TABLE 表1 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
2.4 表操作 — 删除表
-- 删除表(不可逆)
DROP TABLE [IF EXISTS] 表1;
-- 批量删除
DROP TABLE [IF EXISTS] 表1, 表2, 表3;
-- 清空表(保留结构,删除全部数据,不可回滚,重置自增)
TRUNCATE [TABLE] 表1;
-- 临时表(会话结束时自动删除)
CREATE TEMPORARY TABLE 临时表 (
id INT PRIMARY KEY,
字段1 VARCHAR(50)
);
-- 删除临时表
DROP TEMPORARY TABLE [IF EXISTS] 临时表;
| TRUNCATE vs DELETE |
TRUNCATE |
DELETE |
| 本质 |
DDL |
DML |
| 回滚 |
不可回滚 |
可回滚(事务中) |
| 触发器 |
不触发 |
触发 |
| 自增值 |
重置 |
不重置 |
| WHERE 条件 |
不支持 |
支持 |
| 性能 |
快(直接删除数据页) |
慢(逐行删除写日志) |
2.5 视图 (VIEW)
-- 创建视图(封装复杂查询,简化调用)
CREATE [OR REPLACE] VIEW 视图名 [(列别名1, 列别名2)]
AS
SELECT 字段1, 字段2
FROM 表1
WHERE 条件
[WITH [CASCADED | LOCAL] CHECK OPTION]; -- 防止通过视图插入/更新不符合条件的数据
-- 修改视图
ALTER VIEW 视图名 AS SELECT ...;
-- 删除视图
DROP VIEW [IF EXISTS] 视图名;
-- 查看视图定义
SHOW CREATE VIEW 视图名;
WITH CHECK OPTION 区别:
WITH CASCADED CHECK OPTION:检查当前视图及所有依赖视图的条件(默认)
WITH LOCAL CHECK OPTION:仅检查当前视图的条件
2.6 存储过程与函数
-- ======= 修改语句结束符(防止存储过程中的分号提前结束定义)=======
DELIMITER $$
-- ======= 创建存储过程 ========
CREATE PROCEDURE 过程名(
IN 入参名 INT, -- 输入参数
OUT 出参名 VARCHAR(50), -- 输出参数
INOUT 出入参名 DECIMAL(10,2) -- 输入输出参数
)
[DETERMINISTIC | NOT DETERMINISTIC] -- 是否确定性(相同输入总返回相同输出)
[CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA]
[SQL SECURITY DEFINER | INVOKER] -- 按定义者权限还是调用者权限执行
[COMMENT '说明']
BEGIN
-- 变量声明(必须在最前面)
DECLARE 变量1 INT DEFAULT 0;
DECLARE 变量2 VARCHAR(100);
-- 异常处理
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT '发生错误,已回滚';
END;
-- 游标(遍历结果集)
DECLARE cur CURSOR FOR SELECT 字段1, 字段2 FROM 表1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-- 赋值
SET 变量1 = 值1;
SELECT 字段1 INTO 变量2 FROM 表1 WHERE id = 1;
-- 条件判断
IF 条件1 THEN
-- 分支1
ELSEIF 条件2 THEN
-- 分支2
ELSE
-- 分支3
END IF;
-- CASE 语句
CASE 变量1
WHEN 值1 THEN SET 变量2 = 'A';
WHEN 值2 THEN SET 变量2 = 'B';
ELSE SET 变量2 = '其他';
END CASE;
-- 循环 — LOOP(无条件循环,需手动 LEAVE)
标签: LOOP
SET 变量1 = 变量1 - 1;
IF 变量1 <= 0 THEN
LEAVE 标签;
END IF;
END LOOP 标签;
-- 循环 — REPEAT(先执行再判断,至少执行一次)
REPEAT
SET 变量1 = 变量1 + 1;
UNTIL 变量1 >= 10 END REPEAT;
-- 循环 — WHILE(先判断再执行,可能一次都不执行)
WHILE 变量1 < 10 DO
SET 变量1 = 变量1 + 1;
END WHILE;
-- 返回结果(存储过程可返回多个结果集)
SELECT * FROM 表1 WHERE id = 入参名;
-- 设置输出参数
SET 出参名 = '处理完成';
END$$
-- ======= 创建函数(必须有返回值)========
CREATE FUNCTION 函数名(入参1 INT, 入参2 VARCHAR(50))
RETURNS VARCHAR(200) -- 返回值类型
[DETERMINISTIC]
[CONTAINS SQL | READS SQL DATA]
[COMMENT '函数说明']
BEGIN
DECLARE result VARCHAR(200);
-- 函数体内不允许使用 COMMIT / ROLLBACK(隐式事务中不允许显式事务控制)
SET result = CONCAT(入参2, '的编号是', 入参1);
RETURN result;
END$$
-- ======= 恢复默认分隔符 ========
DELIMITER ;
-- 调用存储过程
CALL 过程名(100, @输出变量);
SELECT @输出变量; -- 读取输出参数的值
-- 调用函数
SELECT 函数名(100, '测试');
-- 删除
DROP PROCEDURE [IF EXISTS] 过程名;
DROP FUNCTION [IF EXISTS] 函数名;
-- 查看定义
SHOW CREATE PROCEDURE 过程名;
SHOW CREATE FUNCTION 函数名;
SHOW PROCEDURE STATUS [LIKE '模式']; -- 查看过程状态
SHOW FUNCTION STATUS [LIKE '模式']; -- 查看函数状态
2.7 触发器 (TRIGGER)
CREATE TRIGGER 触发器名
{BEFORE | AFTER} -- 触发时机
{INSERT | UPDATE | DELETE} -- 触发事件
ON 表1 FOR EACH ROW -- 行级触发
[FOLLOWS | PRECEDES 另一个触发器名] -- 指定执行顺序(5.7.2+)
BEGIN
-- NEW.字段 表示插入或更新后的行数据
-- OLD.字段 表示更新前或被删除的行数据
IF NEW.字段1 > 100 THEN
INSERT INTO 日志表(操作, 时间) VALUES ('新增超100的记录', NOW());
END IF;
END;
-- 删除触发器
DROP TRIGGER [IF EXISTS] 触发器名;
-- 查看触发器
SHOW TRIGGERS [FROM 数据库名] [LIKE '模式'];
| 触发时机 |
INSERT |
UPDATE |
DELETE |
| BEFORE 中 NEW |
可用 |
可用 |
❌ |
| BEFORE 中 OLD |
❌ |
可用 |
可用 |
| AFTER 中 NEW |
可用 |
可用 |
❌ |
| AFTER 中 OLD |
❌ |
可用 |
可用 |
2.8 事件 (EVENT) — 定时任务
-- 开启事件调度器(必须)
SET GLOBAL event_scheduler = ON;
CREATE EVENT [IF NOT EXISTS] 事件名
ON SCHEDULE 调度规则
[ON COMPLETION [NOT] PRESERVE] -- 是否保留已完成的事件
[ENABLE | DISABLE | DISABLE ON SLAVE]
[COMMENT '说明']
DO
-- 要执行的SQL(单条或 BEGIN...END 块)
UPDATE 表1 SET 字段1 = 字段1 + 1 WHERE 条件;
-- 调度规则示例:
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR -- 一次性,1小时后执行
ON SCHEDULE EVERY 1 DAY STARTS '2026-01-01 00:00:00' -- 每天执行
ON SCHEDULE EVERY 1 DAY ENDS '2026-12-31 23:59:59' -- 每天执行,结束日期
ON SCHEDULE EVERY 1 HOUR STARTS NOW() ENDS NOW() + INTERVAL 30 DAY -- 每小时执行,30天后停止
-- 管理事件
ALTER EVENT 事件名 ENABLE | DISABLE | RENAME TO 新名称;
DROP EVENT [IF EXISTS] 事件名;
SHOW EVENTS [FROM 数据库名];
三、DML — 数据操作语言
DML 用于操作表中的数据,支持事务回滚。
3.1 INSERT — 插入数据
-- ====== 基础插入 ======
-- 单行插入
INSERT INTO 表1 (字段1, 字段2, 字段3)
VALUES (值1, 值2, 值3);
-- 多行插入(性能更好)
INSERT INTO 表1 (字段1, 字段2)
VALUES
(值a1, 值a2),
(值b1, 值b2),
(值c1, 值c2);
-- 省略列名(必须提供所有列的值,按表定义顺序)
INSERT INTO 表1 VALUES (值1, 值2, 值3);
-- 使用 DEFAULT 关键字
INSERT INTO 表1 (字段1, 字段2)
VALUES (DEFAULT, 'hello'); -- DEFAULT 使用列默认值
-- ====== 高级插入 ======
-- 从查询结果插入(INSERT ... SELECT)
INSERT INTO 表1 (字段1, 字段2)
SELECT 字段1, 字段2 FROM 表2 WHERE 条件;
-- 忽略重复错误(主键/唯一键冲突时静默跳过)
INSERT IGNORE INTO 表1 (id, 字段1) VALUES (1, 'test');
-- 重复时更新(主键/唯一键冲突时执行更新)
INSERT INTO 表1 (id, 字段1, 字段2)
VALUES (1, 'a', 10)
ON DUPLICATE KEY UPDATE
字段1 = VALUES(字段1),
字段2 = 字段2 + VALUES(字段2); -- VALUES() 引用 INSERT 中准备写入的值
-- 替换(如主键冲突,先 DELETE 旧行再 INSERT 新行,不触发 DELETE 触发器)
REPLACE INTO 表1 (id, 字段1) VALUES (1, 'new_value');
-- 从文件导入
LOAD DATA INFILE '/path/to/file.csv'
INTO TABLE 表1
FIELDS TERMINATED BY ',' -- 字段分隔符
ENCLOSED BY '"' -- 字段包围符
LINES TERMINATED BY '\n' -- 行分隔符
IGNORE 1 ROWS -- 跳过首行(标题行)
(字段1, 字段2, 字段3);
3.2 UPDATE — 更新数据
-- ====== 基础更新 ======
-- 单表更新(务必加 WHERE 条件!)
UPDATE 表1
SET 字段1 = 新值1, 字段2 = 新值2
WHERE 条件;
-- 表达式更新
UPDATE 表1
SET 字段1 = 字段1 + 1
WHERE 条件;
-- 使用 ORDER BY 和 LIMIT
UPDATE 表1
SET 字段1 = 字段1 * 1.1
ORDER BY id DESC
LIMIT 10; -- 只更新前 10 行
-- ====== 多表关联更新 ======
-- JOIN 方式
UPDATE 主表
INNER JOIN 从表 ON 主表.id = 从表.主表_id
SET 主表.字段1 = 从表.字段2,
从表.字段3 = 主表.字段4
WHERE 主表.字段5 = '某条件';
-- LEFT JOIN 方式
UPDATE 表1
LEFT JOIN 表2 ON 表1.id = 表2.表1_id
SET 表1.字段1 = COALESCE(表2.字段2, 0); -- COALESCE 处理 NULL
3.3 DELETE — 删除数据
-- ====== 基础删除 ======
-- 单表删除(务必加 WHERE 条件!)
DELETE FROM 表1
WHERE 条件;
-- 带排序和限制的删除
DELETE FROM 表1
ORDER BY 字段1 ASC
LIMIT 100;
-- ====== 多表关联删除 ======
-- 同时删除两表的匹配行
DELETE 主表, 从表
FROM 主表
INNER JOIN 从表 ON 主表.id = 从表.主表_id
WHERE 主表.字段1 = '某条件';
-- 只删从表(保留主表)
DELETE 从表
FROM 从表
INNER JOIN 主表 ON 从表.主表_id = 主表.id
WHERE 主表.字段1 = '某条件';
-- USING 语法(等价写法)
DELETE FROM 从表
USING 从表 INNER JOIN 主表 ON 从表.主表_id = 主表.id
WHERE 主表.字段1 = '某条件';
3.4 事务控制 (Transaction)
-- ====== 基础事务 ======
START TRANSACTION; -- 或 BEGIN / BEGIN WORK
UPDATE 表1 SET 字段1 = 字段1 - 100 WHERE id = 1;
UPDATE 表1 SET 字段1 = 字段1 + 100 WHERE id = 2;
COMMIT; -- 提交(持久化)
-- 或
ROLLBACK; -- 回滚(撤销所有操作)
-- ====== 带保存点的事务 ======
START TRANSACTION;
INSERT INTO 表1 VALUES (1, 'a');
SAVEPOINT sp1; -- 设置保存点
INSERT INTO 表1 VALUES (2, 'b');
SAVEPOINT sp2;
INSERT INTO 表1 VALUES (3, 'c');
ROLLBACK TO SAVEPOINT sp1; -- 回滚到 sp1(2 和 3 撤销,1 保留)
RELEASE SAVEPOINT sp1; -- 释放保存点
COMMIT;
-- ====== 带隔离级别的事务 ======
-- 查看当前隔离级别
SELECT @@transaction_isolation; -- 5.7.20+
SELECT @@tx_isolation; -- 旧版本
-- 设置本次事务的隔离级别(必须在 START TRANSACTION 之前)
SET TRANSACTION ISOLATION LEVEL
READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE;
START TRANSACTION;
-- ... 操作 ...
COMMIT;
-- ====== 手动锁定行 ======
START TRANSACTION;
SELECT * FROM 表1 WHERE id = 1 FOR UPDATE; -- 排他锁(写锁)
-- 或
SELECT * FROM 表1 WHERE id = 1 FOR SHARE; -- 共享锁(读锁,8.0+)
-- 或 (旧版本写法)
SELECT * FROM 表1 WHERE id = 1 LOCK IN SHARE MODE; -- 共享锁(8.0 前)
-- 操作 ...
COMMIT;
四、DQL — 数据查询语言
DQL 的核心是 SELECT 语句。以下按子句的执行顺序逐步展开。
SELECT 语句逻辑执行顺序:FROM → ON → JOIN → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT
4.1 基础查询
-- ====== 最简查询 ======
SELECT 字段1, 字段2 FROM 表1;
-- 查询所有列(慎用,生产环境避免 *)
SELECT * FROM 表1;
-- 去重
SELECT DISTINCT 字段1 FROM 表1;
-- 多列去重
SELECT DISTINCT 字段1, 字段2 FROM 表1;
-- 限制返回行数
SELECT * FROM 表1 LIMIT 10; -- 前 10 行
SELECT * FROM 表1 LIMIT 20, 10; -- 跳过 20 行,取 10 行
SELECT * FROM 表1 LIMIT 10 OFFSET 20; -- 同上(8.0+ 标准语法)
4.2 WHERE 条件过滤
SELECT * FROM 表1
WHERE
-- 比较运算符
字段1 = 值1 -- 等于
AND 字段2 <> 值2 -- 不等于
AND 字段3 != 值3 -- 不等于(同 <>)
AND 字段4 > 值4 -- 大于
AND 字段5 >= 值5 -- 大于等于
AND 字段6 < 值6 -- 小于
AND 字段7 <= 值7 -- 小于等于
-- 逻辑运算符
AND 字段8 IS NULL -- 为空
AND 字段9 IS NOT NULL -- 不为空
AND (字段10 BETWEEN 10 AND 20) -- 区间 [10, 20]
AND 字段11 IN (1, 2, 3) -- 在列表中
AND 字段12 NOT IN (4, 5) -- 不在列表中
AND 字段13 LIKE '%关键字%' -- 模糊匹配(% 任意字符,_ 单个字符)
AND 字段14 REGEXP '^[A-Z].*[0-9]$' -- 正则匹配
-- 安全等于(可用于 NULL 比较)
AND 字段15 <=> NULL; -- NULL <=> NULL → TRUE
-- ====== 模糊匹配详解 ======
-- LIKE 通配符:
-- % : 匹配 0 个或多个字符
-- _ : 匹配 1 个字符
LIKE '张%' -- 以"张"开头
LIKE '%三' -- 以"三"结尾
LIKE '%敏%' -- 包含"敏"
LIKE '张_' -- "张"开头且总共两个字符
LIKE '___' -- 正好三个字符
-- 转义 LIKE 中的特殊字符
LIKE '100\%' ESCAPE '\' -- 匹配 "100%"
-- ====== 正则匹配(REGEXP / RLIKE) ======
REGEXP '^[A-Z]' -- 以大写字母开头
REGEXP '[0-9]$' -- 以数字结尾
REGEXP '^(foo|bar)' -- 以 foo 或 bar 开头
REGEXP '[[:digit:]]+' -- 一个或多个数字
REGEXP '^.{6,20}$' -- 长度 6~20
4.3 JOIN 多表连接 — 中级
-- ====== INNER JOIN(内连接:只返回两表匹配的行)======
SELECT 表1.字段1, 表2.字段2
FROM 表1
INNER JOIN 表2 ON 表1.id = 表2.表1_id; -- ON 连接条件
-- ====== LEFT [OUTER] JOIN(左外连接:保留左表全部,右表匹配不上填 NULL)======
SELECT *
FROM 表1
LEFT JOIN 表2 ON 表1.id = 表2.表1_id;
-- ====== RIGHT [OUTER] JOIN(右外连接:保留右表全部)======
SELECT *
FROM 表1
RIGHT JOIN 表2 ON 表1.id = 表2.表1_id;
-- ====== FULL OUTER JOIN(MySQL 不直接支持,可用 UNION 模拟)======
SELECT * FROM 表1 LEFT JOIN 表2 ON 表1.id = 表2.表1_id
UNION
SELECT * FROM 表1 RIGHT JOIN 表2 ON 表1.id = 表2.表1_id;
-- ====== CROSS JOIN(交叉连接:笛卡尔积,慎用)======
SELECT * FROM 表1 CROSS JOIN 表2; -- 表1 M 行 × 表2 N 行 = M×N 行
-- ====== 自连接(表与自身连接)======
SELECT a.字段1 AS 员工名, b.字段1 AS 上级名
FROM 表1 a
LEFT JOIN 表1 b ON a.上级_id = b.id;
-- ====== USING(当两表连接列同名时可用 USING 简化)======
SELECT * FROM 表1
INNER JOIN 表2 USING (共同列名); -- 等价于 ON 表1.共同列名 = 表2.共同列名
-- ====== NATURAL JOIN(自动用同名同类型列连接,不建议使用,不直观)======
SELECT * FROM 表1 NATURAL JOIN 表2;
-- ====== STRAIGHT_JOIN(强制左表为驱动表)======
SELECT STRAIGHT_JOIN * FROM 表1 JOIN 表2 ON 表1.id = 表2.表1_id;
-- ====== 多表连接 ======
SELECT *
FROM 表1
INNER JOIN 表2 ON 表1.id = 表2.表1_id
LEFT JOIN 表3 ON 表2.id = 表3.表2_id
INNER JOIN 表4 ON 表3.id = 表4.表3_id;
| JOIN 类型 |
说明 |
返回行数 |
INNER JOIN |
交集 |
匹配的行数 |
LEFT JOIN |
左表全留 |
≥ 左表行数 |
RIGHT JOIN |
右表全留 |
≥ 右表行数 |
CROSS JOIN |
笛卡尔积 |
M × N |
NATURAL JOIN |
自动匹配同名列 |
视数据而定 |
4.4 函数 & 表达式 — SELECT 子句中
SELECT
-- 列别名
字段1 AS 别名1,
-- 算术运算
字段2 + 字段3 AS 和,
字段2 - 字段3 AS 差,
字段2 * 字段3 AS 积,
字段2 / 字段3 AS 商,
字段2 DIV 字段3 AS 整除, -- 整数除法
字段2 % 字段3 AS 余数, -- 取模
-- CASE WHEN(行转列 / 条件分类)
CASE
WHEN 条件1 THEN '分类A'
WHEN 条件2 THEN '分类B'
ELSE '其他'
END AS 分类,
-- CASE 简写
CASE 字段1
WHEN 1 THEN '男'
WHEN 2 THEN '女'
ELSE '未知'
END AS 性别,
-- IF 函数
IF(字段1 > 100, '高', '低') AS 高低
FROM 表1;
4.5 GROUP BY 分组聚合 — 中高级
-- ====== 基础分组 ======
SELECT
字段1,
COUNT(*) AS 计数, -- 统计行数
SUM(字段2) AS 总和, -- 求和
AVG(字段2) AS 平均值, -- 平均
MAX(字段2) AS 最大值,
MIN(字段2) AS 最小值,
GROUP_CONCAT(字段3 SEPARATOR ',') AS 拼接列表 -- 将组内值拼接成串
FROM 表1
GROUP BY 字段1;
-- ====== HAVING 过滤分组 ======
SELECT 字段1, COUNT(*) AS cnt
FROM 表1
GROUP BY 字段1
HAVING cnt > 5; -- 过滤聚合结果(WHERE 不能过滤聚合结果)
-- ====== WITH ROLLUP(汇总行) ======
SELECT 字段1, 字段2, SUM(字段3) AS 总和
FROM 表1
GROUP BY 字段1, 字段2
WITH ROLLUP; -- 在每组末尾追加小计行和总计行
-- ====== GROUPING() 函数(判断是否 ROLLUP 汇总行)======
SELECT
IF(GROUPING(字段1), '全部', 字段1) AS 字段1,
IF(GROUPING(字段2), '小计', 字段2) AS 字段2,
SUM(字段3) AS 总和
FROM 表1
GROUP BY 字段1, 字段2 WITH ROLLUP;
聚合函数对比:
| 函数 |
说明 |
忽略 NULL |
适用类型 |
COUNT(*) |
统计总行数 |
— |
任意 |
COUNT(字段) |
统计非 NULL 值个数 |
✅ |
任意 |
COUNT(DISTINCT 字段) |
统计去重非 NULL 值个数 |
✅ |
任意 |
SUM(字段) |
求和 |
✅ |
数值 |
AVG(字段) |
平均值 |
✅ |
数值 |
MAX(字段) |
最大值 |
✅ |
数值/日期/字符串 |
MIN(字段) |
最小值 |
✅ |
数值/日期/字符串 |
GROUP_CONCAT |
拼接组内值 |
✅ |
字符串 |
BIT_AND(字段) |
按位与 |
✅ |
整数 |
BIT_OR(字段) |
按位或 |
✅ |
整数 |
BIT_XOR(字段) |
按位异或 |
✅ |
整数 |
JSON_ARRAYAGG(字段) |
聚合成 JSON 数组 |
✅ |
任意(5.7.22+) |
JSON_OBJECTAGG(key, val) |
聚合成 JSON 对象 |
✅ |
任意(5.7.22+) |
STD(字段) / STDDEV(字段) |
标准差 |
✅ |
数值 |
VARIANCE(字段) |
方差 |
✅ |
数值 |
4.6 子查询 (Subquery) — 高级
-- ====== 标量子查询(返回单个值,可出现在任何需要值的地方)======
SELECT 字段1, (SELECT MAX(字段2) FROM 表2) AS 最大值
FROM 表1;
-- ====== 行子查询(返回单行,可与 (字段1, 字段2) 组合比较)======
SELECT * FROM 表1
WHERE (字段1, 字段2) = (SELECT MAX(字段1), MIN(字段2) FROM 表1);
-- ====== 列子查询(返回单列多行,配合 IN / ANY / ALL)======
SELECT * FROM 表1
WHERE 字段1 IN (SELECT 字段1 FROM 表2 WHERE 条件);
SELECT * FROM 表1
WHERE 字段1 = ANY (SELECT 字段1 FROM 表2); -- = ANY 等价于 IN
SELECT * FROM 表1
WHERE 字段1 > ALL (SELECT 字段1 FROM 表2); -- 大于所有值
SELECT * FROM 表1
WHERE 字段1 > SOME (SELECT 字段1 FROM 表2); -- SOME 同 ANY
-- ====== 表子查询(返回多行多列,必须给别名,放在 FROM 后)======
SELECT t.字段1, t.字段2
FROM (SELECT 字段1, 字段2 FROM 表1 WHERE 条件) AS t
WHERE t.字段1 > 100;
-- ====== EXISTS / NOT EXISTS(判断子查询是否有结果)======
SELECT * FROM 表1
WHERE EXISTS (
SELECT 1 FROM 表2 WHERE 表2.表1_id = 表1.id
);
-- ====== 关联子查询(子查询引用外部表的列,逐行执行)======
SELECT * FROM 表1 a
WHERE a.字段1 > (
SELECT AVG(b.字段1) FROM 表1 b WHERE b.字段2 = a.字段2
);
子查询 vs JOIN 选择原则:
- 子查询语义清晰,适合"是否存在/是否属于"的判断场景
- JOIN 性能通常更好,优化器有更多优化手段
- 关联子查询可能导致 N+1 问题,大表需谨慎
4.7 UNION 联合查询 — 中高级
-- ====== UNION(去重合并)======
SELECT 字段1, 字段2 FROM 表1
UNION
SELECT 字段1, 字段2 FROM 表2;
-- ====== UNION ALL(不去重,性能更好)======
SELECT 字段1, 字段2 FROM 表1
UNION ALL
SELECT 字段1, 字段2 FROM 表2;
-- ====== UNION 配合 ORDER BY / LIMIT ======
-- 整体排序(ORDER BY 在最后)
(SELECT 字段1, 字段2 FROM 表1)
UNION ALL
(SELECT 字段1, 字段2 FROM 表2)
ORDER BY 字段1 DESC
LIMIT 10;
-- 分别 LIMIT
(SELECT 字段1 FROM 表1 LIMIT 5)
UNION ALL
(SELECT 字段1 FROM 表2 LIMIT 5);
| UNION 规则 |
说明 |
| 列数 |
每个 SELECT 必须列数相同 |
| 类型 |
对应列的数据类型兼容 |
| 列名 |
以第一个 SELECT 的列名为准 |
| 排序 |
ORDER BY 只能出现在最后,对合并后结果整体排序 |
| 去重 |
UNION 去重(额外排序开销),UNION ALL 不去重 |
4.8 窗口函数 — 高级 (8.0+)
-- 窗口函数语法:
-- 函数名([参数]) OVER (PARTITION BY 分组列 ORDER BY 排序列 [窗口帧])
-- ====== 排名函数 ======
SELECT
字段1,
字段2,
ROW_NUMBER() OVER (PARTITION BY 字段3 ORDER BY 字段2 DESC) AS row_num, -- 连续排名 1,2,3,4
RANK() OVER (PARTITION BY 字段3 ORDER BY 字段2 DESC) AS rnk, -- 跳跃排名 1,1,3,4
DENSE_RANK() OVER (PARTITION BY 字段3 ORDER BY 字段2 DESC) AS dr, -- 连续排名 1,1,2,3
NTILE(4) OVER (ORDER BY 字段2 DESC) AS bucket, -- 均分4组,标记 1~4
PERCENT_RANK() OVER (ORDER BY 字段2) AS pct_rnk -- 百分比排名 (rank-1)/(n-1)
FROM 表1;
-- ====== 偏移函数 ======
SELECT
id,
字段1,
LAG(字段1, 1, 0) OVER (ORDER BY id) AS 上一行值, -- 取前第 N 行,第三个参数为默认值
LEAD(字段1, 1, 0) OVER (ORDER BY id) AS 下一行值, -- 取后第 N 行
FIRST_VALUE(字段1) OVER (ORDER BY id) AS 第一个值,
LAST_VALUE(字段1) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS 最后一个值,
NTH_VALUE(字段1, 3) OVER (ORDER BY id) AS 第3个值
FROM 表1;
-- ====== 聚合窗口函数 ======
SELECT
id,
字段1,
SUM(字段1) OVER () AS 全局总和,
SUM(字段1) OVER (ORDER BY id) AS 累计和, -- 默认 ROWS UNBOUNDED PRECEDING AND CURRENT ROW
AVG(字段1) OVER (PARTITION BY 字段2) AS 分组内平均,
COUNT(*) OVER (PARTITION BY 字段2 ORDER BY id) AS 分组内累计行数
FROM 表1;
-- ====== 窗口帧 (Window Frame) 详解 ======
-- 仅当 ORDER BY 存在时生效,用于限定当前行的计算范围
-- ROWS(基于物理行号)
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW -- 前2行到当前行
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW -- 分区首行到当前行(默认)
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING -- 当前行到分区末行
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING -- 前1行到后1行(共3行)
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING -- 整个分区
-- RANGE(基于值的逻辑范围,要求 ORDER BY 列值唯一)
RANGE BETWEEN INTERVAL 7 DAY PRECEDING AND CURRENT ROW -- 最近7天
RANGE BETWEEN 100 PRECEDING AND 100 FOLLOWING -- 值相差 ±100 的范围
窗口函数 vs GROUP BY:
| 维度 |
GROUP BY |
窗口函数 |
| 输出行数 |
减少(每分组一行) |
不变(每行都有结果) |
| 可见性 |
只能看到聚合结果 |
既能看到明细,又能看到聚合 |
| 排序 |
结果集整体排序 |
每行都可以有独立的排序上下文 |
4.9 CTE 公共表表达式 — 高级 (8.0+)
-- ====== 普通 CTE ======
WITH
临时表1 AS (
SELECT 字段1, 字段2 FROM 表1 WHERE 条件1
),
临时表2 AS (
SELECT 字段1, 字段3 FROM 表2 WHERE 条件2
)
SELECT t1.字段1, t1.字段2, t2.字段3
FROM 临时表1 t1
LEFT JOIN 临时表2 t2 ON t1.字段1 = t2.字段1;
-- ====== 递归 CTE(处理树形结构 / 层级数据)======
WITH RECURSIVE 递归CTE AS (
-- 初始查询(锚点成员)
SELECT id, 上级id, 字段1, 1 AS 层级
FROM 表1
WHERE 上级id IS NULL
UNION ALL
-- 递归查询(递归成员)
SELECT t.id, t.上级id, t.字段1, r.层级 + 1
FROM 表1 t
INNER JOIN 递归CTE r ON t.上级id = r.id
)
SELECT * FROM 递归CTE ORDER BY 层级;
-- ====== CTE 中可使用窗口函数 ======
WITH ranked AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY 字段2 ORDER BY 字段3 DESC) AS rn
FROM 表1
)
SELECT * FROM ranked WHERE rn <= 3; -- 每组取前 N 条
-- ====== CTE 可被多次引用 ======
WITH stats AS (
SELECT AVG(字段1) AS avg_val FROM 表1
)
SELECT * FROM 表1, stats
WHERE 表1.字段1 > stats.avg_val;
4.10 ORDER BY 排序
SELECT * FROM 表1
ORDER BY
字段1 ASC, -- 升序(默认)
字段2 DESC, -- 降序
FIELD(字段3, 'A','B','C'), -- 按自定义顺序排序
字段4 IS NULL, -- NULL 默认排在最前面;此写法将 NULL 排到最后
RAND(); -- 随机排序(慎用,大数据量极慢)
-- NULL 排序规则控制
SELECT * FROM 表1 ORDER BY 字段1 ASC;
-- ASC → NULL FIRST(默认)
-- DESC → NULL LAST(默认)
-- 自定义 NULL 排序
SELECT * FROM 表1 ORDER BY -字段1 DESC; -- 让 NULL 排在前面(降序时)
SELECT * FROM 表1 ORDER BY 字段1 IS NULL, 字段1; -- NULL 放最后
4.11 查询提示 (Hints) — 高级调优
-- ====== 索引提示 ======
SELECT * FROM 表1 USE INDEX (idx_字段1) WHERE 字段1 = '值'; -- 建议使用
SELECT * FROM 表1 IGNORE INDEX (idx_字段1) WHERE 字段1 = '值'; -- 忽略某索引
SELECT * FROM 表1 FORCE INDEX (idx_字段1) WHERE 字段1 = '值'; -- 强制使用
-- ====== 优化器提示(8.0+) ======
SELECT /*+ JOIN_ORDER(表2, 表1) */ -- 指定连接顺序
/*+ SET_VAR(sort_buffer_size = 16M) */ -- 临时修改会话变量
/*+ NO_RANGE_OPTIMIZATION(表1 idx_字段2) */ -- 关闭范围优化
*
FROM 表1
INNER JOIN 表2 ON 表1.id = 表2.表1_id;
-- 常用优化器提示:
-- BKA(t1, t2) — 启用 Batched Key Access
-- NO_BKA(t1) — 禁用 BKA
-- BNL(t1, t2) — 启用 Block Nested Loop
-- NO_BNL(t1) — 禁用 BNL
-- MRR(t1) — 启用 Multi-Range Read
-- NO_MRR(t1) — 禁用 MRR
-- SEMIJOIN / NO_SEMIJOIN — 控制半连接策略
-- DERIVED_MERGE / NO_DERIVED_MERGE — 是否将派生表合并到外层查询
五、DCL — 数据控制语言
DCL 用于管理用户权限、访问控制和事务。
5.1 用户管理
-- ====== 查看用户 ======
SELECT User, Host FROM mysql.user;
-- 查看当前登录用户
SELECT USER(); -- 格式:user@host
SELECT CURRENT_USER(); -- 已验证的用户
-- ====== 创建用户 ======
CREATE USER '用户名'@'主机'
IDENTIFIED BY '密码';
CREATE USER '用户名'@'主机'
IDENTIFIED WITH mysql_native_password BY '密码' -- 指定认证插件(兼容老客户端)
PASSWORD EXPIRE INTERVAL 90 DAY -- 密码 90 天过期
FAILED_LOGIN_ATTEMPTS 5 -- 失败 5 次锁定(8.0.19+)
PASSWORD_LOCK_TIME 3 -- 锁定 3 天(8.0.19+)
MAX_QUERIES_PER_HOUR 1000 -- 每小时最大查询数
MAX_UPDATES_PER_HOUR 500 -- 每小时最大更新数
MAX_CONNECTIONS_PER_HOUR 50 -- 每小时最大连接数
MAX_USER_CONNECTIONS 5; -- 最大同时连接数
-- 主机匹配规则:
-- 'user'@'%' — 任意主机
-- 'user'@'localhost' — 仅本机
-- 'user'@'192.168.1.%' — 匹配 IP 段
-- 'user'@'192.168.1.100' — 精确 IP
-- 'user'@'%.example.com' — 匹配域名
-- ====== 修改用户 ======
ALTER USER '用户名'@'主机'
IDENTIFIED BY '新密码'
PASSWORD EXPIRE; -- 强制下次登录改密码
-- 锁定/解锁用户
ALTER USER '用户名'@'主机' ACCOUNT LOCK;
ALTER USER '用户名'@'主机' ACCOUNT UNLOCK;
-- ====== 修改当前用户密码 ======
ALTER USER USER() IDENTIFIED BY '新密码';
SET PASSWORD = '新密码'; -- 旧语法
-- ====== 重命名用户 ======
RENAME USER '旧用户名'@'主机' TO '新用户名'@'主机';
-- ====== 删除用户 ======
DROP USER [IF EXISTS] '用户名'@'主机';
5.2 权限管理
-- ====== 授予权限 ======
GRANT 权限列表 ON 数据库名.表名 TO '用户名'@'主机';
-- 权限列表可授予多个,逗号分隔
GRANT SELECT, INSERT, UPDATE, DELETE
ON 数据库名.表1
TO '用户名'@'主机';
-- 授予所有权限(不包含 GRANT OPTION)
GRANT ALL PRIVILEGES ON 数据库名.* TO '用户名'@'主机';
-- 授予 + 允许该用户再授权给他人
GRANT ALL PRIVILEGES ON 数据库名.* TO '用户名'@'主机' WITH GRANT OPTION;
-- 授予角色(8.0+)
GRANT '角色名' TO '用户名'@'主机';
-- ====== 查看权限 ======
SHOW GRANTS FOR '用户名'@'主机';
SHOW GRANTS FOR CURRENT_USER(); -- 查看当前用户权限
-- ====== 撤销权限 ======
REVOKE 权限列表 ON 数据库名.表名 FROM '用户名'@'主机';
REVOKE ALL PRIVILEGES, GRANT OPTION FROM '用户名'@'主机'; -- 撤销所有
-- ====== 刷新权限(对直接操作 mysql.user 表的变更生效)======
FLUSH PRIVILEGES;
常用权限列表:
| 级别 |
权限 |
说明 |
| 全局 |
ALL [PRIVILEGES] |
所有权限(不含 GRANT OPTION) |
| 全局 |
USAGE |
无权限(仅连接) |
| 数据库 |
CREATE |
创建表 |
| 数据库 |
DROP |
删除表 |
| 数据库 |
ALTER |
修改表结构 |
| 数据库 |
INDEX |
创建/删除索引 |
| 数据库 |
CREATE VIEW |
创建视图 |
| 数据库 |
SHOW VIEW |
查看视图定义 |
| 数据库 |
CREATE ROUTINE |
创建存储过程/函数 |
| 数据库 |
ALTER ROUTINE |
修改/删除存储过程/函数 |
| 数据库 |
EXECUTE |
执行存储过程/函数 |
| 数据库 |
EVENT |
管理事件 |
| 数据库 |
TRIGGER |
管理触发器 |
| 表级 |
SELECT |
查询数据 |
| 表级 |
INSERT |
插入数据 |
| 表级 |
UPDATE |
更新数据 |
| 表级 |
DELETE |
删除数据 |
| 表级 |
REFERENCES |
创建外键 |
| 列级 |
SELECT(字段1,字段2) |
只允许查指定列 |
| 列级 |
INSERT(字段1,字段2) |
只允许向指定列插入 |
| 列级 |
UPDATE(字段1,字段2) |
只允许更新指定列 |
| 系统 |
SUPER |
超级权限(KILL / CHANGE MASTER 等) |
| 系统 |
PROCESS |
查看所有线程(SHOW PROCESSLIST) |
| 系统 |
FILE |
读写文件(LOAD_FILE / SELECT ... INTO OUTFILE) |
| 系统 |
RELOAD |
刷新(FLUSH) |
| 系统 |
SHUTDOWN |
关闭服务器 |
| 系统 |
REPLICATION CLIENT |
查看复制状态 |
| 系统 |
REPLICATION SLAVE |
作为从库复制 |
| 系统 |
CREATE USER |
创建用户 |
| 角色 |
CREATE ROLE |
创建角色(8.0+) |
权限作用范围(从大到小):*.*(全局) → 数据库名.*(库级) → 数据库名.表名(表级) → 数据库名.表名(列)(列级)
5.3 角色管理 (8.0+)
-- 创建角色
CREATE ROLE '角色名';
-- 给角色授权
GRANT SELECT, INSERT ON 数据库名.* TO '角色名';
-- 将角色授予用户
GRANT '角色名' TO '用户名'@'主机';
-- 设置用户默认角色(否则登录后需手动激活)
SET DEFAULT ROLE '角色名' TO '用户名'@'主机';
SET DEFAULT ROLE ALL TO '用户名'@'主机'; -- 自动激活所有角色
-- 当前会话激活/停用角色
SET ROLE '角色名';
SET ROLE NONE; -- 停用所有角色
-- 撤销角色的用户
REVOKE '角色名' FROM '用户名'@'主机';
-- 删除角色
DROP ROLE [IF EXISTS] '角色名';
5.4 其他管理命令
-- ====== 查看 MySQL 版本 ======
SELECT VERSION();
-- ====== 查看所有连接/线程 ======
SHOW [FULL] PROCESSLIST;
-- 终止某个连接
KILL [CONNECTION | QUERY] 线程ID;
-- 注意:
-- KILL CONNECTION — 终止连接 + 正在执行的语句(默认)
-- KILL QUERY — 只终止当前语句,不关闭连接
-- ====== 查看状态变量 ======
SHOW STATUS [LIKE '模式'];
SHOW GLOBAL STATUS LIKE '%connection%';
-- ====== 查看系统变量 ======
SHOW VARIABLES [LIKE '模式'];
SHOW GLOBAL VARIABLES LIKE '%innodb_buffer_pool%';
-- 动态修改变量
SET [GLOBAL | SESSION] 变量名 = 值; -- GLOBAL 影响新连接,SESSION 仅当前会话
-- ====== 查看表信息 ======
SHOW TABLE STATUS [FROM 数据库名] [LIKE '模式'];
SHOW CREATE TABLE 表1;
DESCRIBE 表1; -- 或 DESC 表1;
SHOW COLUMNS FROM 表1;
SHOW INDEX FROM 表1;
-- ====== 查看库/表列表 ======
SHOW DATABASES;
SHOW TABLES [FROM 数据库名];
-- ====== 查看引擎信息 ======
SHOW ENGINES;
SHOW ENGINE InnoDB STATUS\G
-- ====== 刷新操作 ======
FLUSH PRIVILEGES; -- 刷新权限表
FLUSH TABLES; -- 关闭所有表
FLUSH TABLES WITH READ LOCK; -- 全局读锁(备份用)
FLUSH LOGS; -- 刷新日志
FLUSH STATUS; -- 重置状态变量
-- ====== 分析/检查/修复/优化表 ======
ANALYZE TABLE 表1; -- 更新索引统计(影响执行计划)
CHECK TABLE 表1; -- 检查表错误
REPAIR TABLE 表1; -- 修复表(MyISAM)
OPTIMIZE TABLE 表1; -- 优化表(碎片整理)
-- ====== 导出查询结果到文件 ======
SELECT * FROM 表1
INTO OUTFILE '/tmp/export.csv'
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
LINES TERMINATED BY '\n';
六、常用函数速查
6.1 字符串函数
| 函数 |
说明 |
示例 |
CONCAT(s1, s2, ...) |
拼接字符串 |
CONCAT('a','b') → 'ab' |
CONCAT_WS(sep, s1, s2, ...) |
带分隔符拼接 |
CONCAT_WS('-','a','b') → 'a-b' |
LENGTH(s) |
字节长度 |
LENGTH('你好') → 6 |
CHAR_LENGTH(s) |
字符长度 |
CHAR_LENGTH('你好') → 2 |
LEFT(s, n) / RIGHT(s, n) |
取左/右 n 个字符 |
|
SUBSTRING(s, start, len) |
截取子串(start 从 1 开始) |
SUBSTRING('hello',2,3) → 'ell' |
SUBSTRING_INDEX(s, delim, n) |
按分隔符截取 |
SUBSTRING_INDEX('a,b,c',',',2) → 'a,b' |
REPLACE(s, from, to) |
替换 |
REPLACE('hello','l','x') → 'hexxo' |
TRIM(s) / LTRIM(s) / RTRIM(s) |
去除空格 |
|
UPPER(s) / LOWER(s) |
大小写转换 |
|
REVERSE(s) |
反转 |
REVERSE('abc') → 'cba' |
REPEAT(s, n) |
重复 n 次 |
|
LPAD(s, len, pad) / RPAD(s, len, pad) |
左右填充到指定长度 |
|
INSTR(s, sub) / LOCATE(sub, s) |
子串第一次出现位置 |
|
FORMAT(n, d) |
数字千分位格式化 |
FORMAT(1234567,2) → '1,234,567.00' |
6.2 数值函数
| 函数 |
说明 |
示例 |
ABS(n) |
绝对值 |
ABS(-5) → 5 |
CEIL(n) / CEILING(n) |
向上取整 |
CEIL(3.1) → 4 |
FLOOR(n) |
向下取整 |
FLOOR(3.9) → 3 |
ROUND(n, d) |
四舍五入到 d 位小数 |
ROUND(3.1415, 2) → 3.14 |
TRUNCATE(n, d) |
截断到 d 位小数 |
TRUNCATE(3.149, 2) → 3.14 |
MOD(n, m) / n % m |
取模 |
MOD(10, 3) → 1 |
POW(x, y) / POWER(x, y) |
幂运算 |
POW(2, 3) → 8 |
SQRT(n) |
平方根 |
SQRT(9) → 3 |
RAND([seed]) |
随机数 [0, 1) |
FLOOR(RAND()*100) → 0~99 随机 |
SIGN(n) |
符号 |
SIGN(-5) → -1 |
GREATEST(a, b, ...) |
最大值 |
|
LEAST(a, b, ...) |
最小值 |
|
6.3 日期时间函数
| 函数 |
说明 |
示例 |
NOW() / CURRENT_TIMESTAMP |
当前日期时间 |
2026-05-13 14:30:00 |
CURDATE() / CURRENT_DATE |
当前日期 |
2026-05-13 |
CURTIME() / CURRENT_TIME |
当前时间 |
14:30:00 |
DATE(datetime) |
提取日期部分 |
|
TIME(datetime) |
提取时间部分 |
|
YEAR(d) / MONTH(d) / DAY(d) |
提取年/月/日 |
|
HOUR(t) / MINUTE(t) / SECOND(t) |
提取时/分/秒 |
|
QUARTER(d) |
季度 (1~4) |
|
DAYOFWEEK(d) |
星期几 (1=周日, 7=周六) |
|
WEEKDAY(d) |
星期几 (0=周一, 6=周日) |
|
DAYOFYEAR(d) |
一年中第几天 |
|
WEEK(d) |
一年中第几周 |
|
DATE_FORMAT(d, fmt) |
格式化日期 |
DATE_FORMAT(NOW(),'%Y-%m-%d') |
STR_TO_DATE(s, fmt) |
字符串转日期 |
STR_TO_DATE('2026-05-13','%Y-%m-%d') |
DATE_ADD(d, INTERVAL n unit) |
日期加法 |
DATE_ADD(NOW(), INTERVAL 7 DAY) |
DATE_SUB(d, INTERVAL n unit) |
日期减法 |
DATE_SUB(NOW(), INTERVAL 1 MONTH) |
DATEDIFF(d1, d2) |
日期差(天数) |
DATEDIFF('2026-05-20','2026-05-13') → 7 |
TIMESTAMPDIFF(unit, d1, d2) |
时间差(指定单位) |
TIMESTAMPDIFF(HOUR, t1, t2) |
UNIX_TIMESTAMP([d]) |
转 Unix 时间戳 |
|
FROM_UNIXTIME(ts) |
Unix 时间戳转日期 |
|
LAST_DAY(d) |
所在月最后一天 |
|
EXTRACT(unit FROM d) |
提取时间部分 |
EXTRACT(YEAR FROM NOW()) |
DATE_FORMAT 常用格式符:
| 格式符 |
说明 |
示例 |
%Y |
四位年 |
2026 |
%y |
两位年 |
26 |
%m |
两位月 |
05 |
%c |
月(无前导零) |
5 |
%d |
两位日 |
13 |
%H |
24小时制 |
14 |
%h |
12小时制 |
02 |
%i |
分钟 |
30 |
%s |
秒 |
00 |
%W |
星期全名 |
Wednesday |
%a |
星期缩写 |
Wed |
%M |
月份全名 |
May |
%b |
月份缩写 |
May |
%p |
AM/PM |
PM |
%j |
年内第几天 |
133 |
%T |
完整时间 |
14:30:00 |
%r |
12小时制时间 |
02:30:00 PM |
INTERVAL 单位关键字:MICROSECOND / SECOND / MINUTE / HOUR / DAY / WEEK / MONTH / QUARTER / YEAR
6.4 条件函数 / 流程控制
| 函数 |
说明 |
示例 |
IF(cond, v1, v2) |
条件判断 |
IF(score>=60, '及格', '不及格') |
IFNULL(v1, v2) |
v1 为 NULL 时返回 v2 |
IFNULL(字段1, 0) |
NULLIF(v1, v2) |
v1=v2 时返回 NULL |
NULLIF(a, 0) — 避免除零 |
COALESCE(v1, v2, ...) |
返回第一个非 NULL 值 |
COALESCE(字段1, 字段2, '默认') |
CASE WHEN ... THEN ... ELSE ... END |
多条件判断 |
见 4.4 节 |
6.5 JSON 函数 (5.7+)
| 函数 |
说明 |
JSON_EXTRACT(doc, path) / doc->'$.key' |
提取 JSON 值(保留类型) |
doc->>'$.key' |
提取 JSON 值并转为字符串 |
JSON_UNQUOTE(val) |
去除 JSON 值的引号 |
JSON_SET(doc, path, val, ...) |
插入/更新 JSON 字段 |
JSON_REPLACE(doc, path, val) |
替换已有字段 |
JSON_REMOVE(doc, path) |
删除字段 |
JSON_ARRAY(val, ...) |
创建 JSON 数组 |
JSON_OBJECT(key, val, ...) |
创建 JSON 对象 |
JSON_CONTAINS(doc, val) |
是否包含 |
JSON_LENGTH(doc) |
JSON 数组长度 / 对象键数 |
JSON_KEYS(doc) |
获取所有键 |
JSON_TYPE(doc) |
查看 JSON 值类型 |
JSON_VALID(str) |
判断是否为合法 JSON |
JSON_ARRAYAGG(col) |
聚合为 JSON 数组 |
JSON_OBJECTAGG(key, val) |
聚合为 JSON 对象 |
JSON_TABLE(doc, path COLUMNS(...)) |
JSON 转关系表(8.0+) |
6.6 加密函数
| 函数 |
说明 |
MD5(str) |
MD5 哈希(128 位,不推荐用于密码) |
SHA1(str) / SHA(str) |
SHA-1 哈希(160 位) |
SHA2(str, hash_len) |
SHA-2 哈希(224/256/384/512 位) |
AES_ENCRYPT(str, key) |
AES 加密 |
AES_DECRYPT(crypt, key) |
AES 解密 |
RANDOM_BYTES(n) |
生成 n 字节随机数据(5.7+) |
6.7 类型转换函数
| 函数 |
说明 |
CAST(expr AS type) |
类型转换(ANSI 标准) |
CONVERT(expr, type) |
类型转换(MySQL 风格) |
CONVERT(expr USING charset) |
字符集转换 |
支持的目标类型:CHAR / DATE / DATETIME / TIME / DECIMAL / SIGNED [INTEGER] / UNSIGNED [INTEGER] / BINARY / JSON
附录:关键概念速查
A. 存储引擎对比
| 特性 |
InnoDB |
MyISAM |
MEMORY |
| 事务 |
✅ |
❌ |
❌ |
| 行级锁 |
✅ |
❌(表锁) |
❌(表锁) |
| 外键 |
✅ |
❌ |
❌ |
| 崩溃恢复 |
✅ |
❌ |
❌(重启数据丢失) |
| 全文索引 |
✅(5.6+) |
✅ |
❌ |
| 空间索引 |
✅(5.7+) |
✅ |
❌ |
| 数据存储 |
磁盘 |
磁盘 |
内存 |
| MVCC |
✅ |
❌ |
❌ |
| 压缩 |
✅ |
✅ |
❌ |
B. 事务隔离级别及问题
| 隔离级别 |
脏读 |
不可重复读 |
幻读 |
| READ UNCOMMITTED |
✅ |
✅ |
✅ |
| READ COMMITTED |
❌ |
✅ |
✅ |
| REPEATABLE READ (默认) |
❌ |
❌ |
✅(InnoDB 通过 Next-Key Lock 防止) |
| SERIALIZABLE |
❌ |
❌ |
❌ |
脏读:读到其他事务未提交的数据。 不可重复读:同一事务内两次读取同一行,结果不同(被其他事务 UPDATE)。 幻读:同一事务内两次查询同一条件,结果集行数不同(被其他事务 INSERT/DELETE)。
C. EXPLAIN 执行计划关键字段
| 字段 |
说明 |
id |
查询序号(越大越先执行,相同则从上到下) |
select_type |
查询类型(SIMPLE / PRIMARY / SUBQUERY / DERIVED / UNION 等) |
table |
访问的表 |
type |
访问类型(从优到劣:system > const > eq_ref > ref > range > index > ALL) |
possible_keys |
可能使用的索引 |
key |
实际使用的索引 |
key_len |
索引使用的字节数 |
ref |
与索引比较的列或常量 |
rows |
预估扫描行数 |
filtered |
按条件过滤后的行百分比 |
Extra |
额外信息(Using index / Using filesort / Using temporary 等) |
D. 索引使用原则
- 最左前缀原则:复合索引
(a, b, c),查询条件必须从最左列开始,不能跳过中间列。
- 覆盖索引:查询的列全在索引中(Extra 显示
Using index),无需回表。
- 避免索引失效:
WHERE 子句中对索引列使用函数或运算(如 WHERE YEAR(字段) = 2026)
- 前导模糊匹配(
LIKE '%xxx')
- 隐式类型转换(
WHERE 字段 = 123 而字段是 VARCHAR)
OR 条件中部分列无索引
!= / <> / NOT IN 可能导致全表扫描
IS NULL / IS NOT NULL 是否走索引取决于数据分布
文档版本:MySQL 8.0+ 为基准,兼容 5.7 生成日期:2026-05-13