一、命名约定与占位符说明

占位符 含义
表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