以下是一份专为 Java 后端开发者(Spring Boot 团队) 量身定制的 MySQL SQL 语句分类详解与标准使用指南,系统梳理 SQL 的五大分类(DDL、DML、DQL、DCL、TCL),每类均提供企业级标准示例 + 中文注释说明,确保团队理解透彻、书写规范、落地一致。
📘 MySQL SQL 语句完整分类指南(企业级标准版)
适用对象:Java 后端开发、测试、DBA、技术负责人
目标:统一 SQL 认知,规范编写,提升代码质量与系统稳定性
版本要求:MySQL 8.0+(推荐)
引擎要求:InnoDB(事务支持、行级锁)
核心原则:可读、可维护、可追溯、高性能
一、SQL 语句五大分类总览
| 分类 | 全称 | 英文全称 | 作用 | 是否影响数据 | 是否可回滚 |
|---|---|---|---|---|---|
| DDL | 数据定义语言 | Data Definition Language | 定义/修改数据库结构 | ✅ 影响结构 | ❌ 不可回滚 |
| DML | 数据操作语言 | Data Manipulation Language | 增删改数据记录 | ✅ 影响数据 | ✅ 可回滚(事务内) |
| DQL | 数据查询语言 | Data Query Language | 查询数据记录 | ❌ 只读 | ✅ 可回滚(仅读,无副作用) |
| DCL | 数据控制语言 | Data Control Language | 控制用户权限与访问 | ✅ 影响安全策略 | ❌ 不可回滚 |
| TCL | 事务控制语言 | Transaction Control Language | 管理事务提交/回滚 | ✅ 影响事务状态 | ✅ 本身是回滚机制 |
✅ 记忆口诀:
“定(DDL)操(DML)查(DQL)控(DCL)交(TCL)”
二、详细分类说明与标准示例(含中文注释)
✅ 1. DDL(Data Definition Language)——定义数据库结构
作用:创建、修改、删除数据库、表、索引、视图等结构对象,不操作数据本身。
特点:自动提交(Autocommit),执行后立即生效,无法回滚。
📌 标准示例(带中文注释)
-- 1. 创建数据库(推荐指定字符集与排序规则)
CREATE DATABASE IF NOT EXISTS `order_system`
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci
COMMENT '订单系统主数据库,支持中文、emoji、多语言';
-- 2. 删除数据库(生产环境慎用!)
DROP DATABASE IF EXISTS `old_system`; -- 仅用于测试或迁移,生产环境禁止随意删除
-- 3. 创建表(企业级标准模板)
CREATE TABLE `user` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键,自增,无符号,支持18亿+用户',
`username` VARCHAR(50) NOT NULL UNIQUE COMMENT '登录用户名,唯一约束,防止重复注册',
`email` VARCHAR(100) NOT NULL UNIQUE COMMENT '邮箱,唯一,用于找回密码与通知',
`password` VARCHAR(255) NOT NULL COMMENT 'BCrypt 加密后的密码,长度固定255',
`phone` VARCHAR(20) NULL COMMENT '手机号,可为空,用于短信验证',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间,自动填充',
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间,自动更新',
`is_deleted` TINYINT(1) DEFAULT 0 COMMENT '逻辑删除标志:0=正常,1=已删除(软删除)',
-- 主键约束(推荐显式声明)
PRIMARY KEY (`id`),
-- 普通索引:加速 WHERE 查询
INDEX `idx_username` (`username`) COMMENT '加速根据用户名登录查询',
INDEX `idx_email` (`email`) COMMENT '加速邮箱查找(找回密码)',
INDEX `idx_created_at` (`created_at`) COMMENT '按创建时间排序/分页查询优化',
-- 联合索引:多条件查询优化(注意顺序)
INDEX `idx_email_created` (`email`, `created_at`) COMMENT '常用于:按邮箱+时间范围查询'
) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COMMENT='用户基础信息表(逻辑删除表)';
-- ⚠️ 注意:utf8mb4 支持 emoji(如 😊),utf8 只支持 3 字节,易导致插入失败!
✅ 企业最佳实践(DDL 规范)
| 规范项 | 说明 |
|---|---|
| 表名 | 全小写 + 下划线,如 user_order,禁止 UserOrder |
| 字段名 | 同上,避免驼峰(如 userName) |
| 主键 | 必须用 BIGINT UNSIGNED AUTO_INCREMENT,避免 UUID(索引碎片大) |
| 字符集 | 统一使用 utf8mb4,避免中文/emoji 存储异常 |
| 逻辑删除 | 所有业务表必须包含 is_deleted TINYINT(1) DEFAULT 0 |
| 注释 | 每个字段、表必须有 COMMENT,便于文档生成与团队协作 |
| 索引命名 | idx_字段名 或 idx_字段1_字段2,便于排查慢查询 |
| 禁止 DROP | 生产环境禁止直接 DROP TABLE,应通过 ALTER TABLE ... RENAME 隔离 |
✅ 2. DML(Data Manipulation Language)——操作数据记录
作用:对表中的数据记录进行增、删、改操作,属于事务性操作,可回滚。
核心命令:INSERT、UPDATE、DELETE
📌 标准示例(带中文注释)
-- 1. 插入数据(INSERT)——推荐批量插入,提升性能
-- ✅ 单条插入(适合少量数据)
INSERT INTO `user` (
`username`, `email`, `password`, `phone`
) VALUES (
'zhangsan', 'zhangsan@company.com', '$2a$10$abc123...', '13800138000'
);
-- ✅ 批量插入(推荐!减少网络往返,提升吞吐量)
INSERT INTO `user` (
`username`, `email`, `password`, `phone`
) VALUES
('lisi', 'lisi@company.com', '$2a$10$xyz456...', '13900139000'),
('wangwu', 'wangwu@company.com', '$2a$10$def789...', NULL),
('zhaoliu', 'zhaoliu@company.com', '$2a$10$ghi012...', '13700137000');
-- ❌ 绝对禁止:不指定字段名(易因表结构变更崩溃)
INSERT INTO `user` VALUES (1, 'xxx', 'xxx', ...); -- 不可维护,团队禁止!
-- 2. 更新数据(UPDATE)——必须带 WHERE 条件,禁止全表更新!
-- ✅ 正确:通过主键精准更新
UPDATE `user`
SET `phone` = '13600136000', `updated_at` = NOW()
WHERE `id` = 1001;
-- ✅ 正确:通过唯一索引更新
UPDATE `user`
SET `email` = 'newemail@company.com', `updated_at` = NOW()
WHERE `username` = 'zhangsan';
-- ❌ 绝对禁止:无 WHERE 条件(生产事故高发区!)
UPDATE `user` SET `phone` = '11111111111'; -- 会修改所有用户电话!致命错误!
-- 3. 删除数据(DELETE)——禁止物理删除!必须逻辑删除!
-- ✅ 正确:逻辑删除(标记为删除)
UPDATE `user`
SET `is_deleted` = 1, `updated_at` = NOW()
WHERE `id` = 1001;
-- ❌ 绝对禁止:物理删除(不可恢复)
DELETE FROM `user` WHERE `id` = 1001; -- 一旦误删,无法恢复!禁止使用!
✅ 企业最佳实践(DML 规范)
| 规范项 | 说明 |
|---|---|
| INSERT | 必须显式列出字段名,禁止 INSERT INTO table VALUES (...) |
| UPDATE | 必须使用主键或唯一索引作为 WHERE 条件,禁止全表更新 |
| DELETE | 禁止物理删除,统一使用 is_deleted = 1 逻辑删除 |
| 批量操作 | >100 条记录必须使用批量插入/更新,避免循环单条执行 |
| 参数化 | Java 代码中必须使用 PreparedStatement 或 MyBatis #{},禁止拼接 SQL(防注入) |
| 事务包裹 | 所有 DML 操作必须在 @Transactional 事务中执行,保证一致性 |
✅ 3. DQL(Data Query Language)——查询数据记录
作用:从数据库中只读查询数据,是开发中最频繁使用的 SQL 类型。
核心命令:SELECT
特点:不修改数据,可安全执行,支持事务隔离级别控制。
📌 标准示例(带中文注释)
-- 1. 基础查询:只查需要的字段,禁止 SELECT *
-- ✅ 正确:明确指定字段
SELECT
`id`,
`username`,
`email`,
`created_at`
FROM `user`
WHERE `is_deleted` = 0
AND `username` = 'zhangsan';
-- ❌ 绝对禁止:SELECT *(浪费网络、降低缓存命中、易出错)
SELECT * FROM `user` WHERE username = 'zhangsan';
-- 2. 条件查询:WHERE + 索引优化
-- ✅ 使用索引字段查询(确保命中索引)
SELECT `id`, `username`, `email`
FROM `user`
WHERE `email` = 'lisi@company.com'
AND `is_deleted` = 0;
-- ✅ 范围查询(时间范围)
SELECT `id`, `username`, `created_at`
FROM `user`
WHERE `is_deleted` = 0
AND `created_at` BETWEEN '2025-01-01 00:00:00' AND '2025-10-16 23:59:59'
ORDER BY `created_at` DESC;
-- 3. 排序与分页:避免大偏移量分页
-- ✅ 正确:小偏移量分页(适用于首页、前100页)
SELECT `id`, `username`, `email`
FROM `user`
WHERE `is_deleted` = 0
ORDER BY `created_at` DESC
LIMIT 10 OFFSET 0; -- 第1页,每页10条
-- ✅ 正确:大偏移量分页优化 → 使用“游标分页”(基于ID/时间)
-- 假设上一页最后一条记录的 ID 是 5000
SELECT `id`, `username`, `email`
FROM `user`
WHERE `is_deleted` = 0
AND `id` < 5000 -- 使用上一页最后ID作为游标
ORDER BY `id` DESC
LIMIT 10;
-- 4. 多表关联查询(JOIN)——谨慎使用,注意索引
-- ✅ 正确:INNER JOIN + 索引字段 + 明确字段
SELECT
u.`username`,
o.`order_no`,
o.`amount`,
o.`created_at`
FROM `user` u
INNER JOIN `order` o ON u.`id` = o.`user_id` -- 关联字段必须有索引
WHERE u.`is_deleted` = 0
AND o.`is_deleted` = 0
AND o.`status` = 'PAID'
ORDER BY o.`created_at` DESC
LIMIT 20;
-- ✅ 使用别名提升可读性(推荐)
-- u 表示 user,o 表示 order,清晰易懂
-- 5. 聚合函数:统计类查询(常用于报表)
-- ✅ 统计用户总数
SELECT COUNT(*) AS `total_users`
FROM `user`
WHERE `is_deleted` = 0;
-- ✅ 统计每个用户的订单数(分组聚合)
SELECT
u.`username`,
COUNT(o.`id`) AS `order_count`,
SUM(o.`amount`) AS `total_amount`
FROM `user` u
LEFT JOIN `order` o ON u.`id` = o.`user_id` AND o.`is_deleted` = 0
WHERE u.`is_deleted` = 0
GROUP BY u.`id`, u.`username`
HAVING `order_count` > 5 -- 筛选下单超过5次的用户
ORDER BY `total_amount` DESC;
✅ 企业最佳实践(DQL 规范)
| 规范项 | 说明 |
|---|---|
| **禁止 SELECT *** | 必须显式列出字段,提升性能与稳定性 |
| 分页优化 | >1000 页必须改用“游标分页”(基于 ID/时间),避免 LIMIT 1000000, 10 |
| JOIN 数量 | 单次查询 JOIN 表不超过 3 张,复杂逻辑拆解到程序层 |
| 聚合查询 | 避免在高并发接口中使用 GROUP BY + COUNT(*),建议用缓存或异步统计 |
| EXPLAIN 必查 | 所有复杂查询必须用 EXPLAIN 检查是否命中索引 |
| 注释查询意图 | 复杂查询顶部加注释说明用途(如:用于订单报表导出) |
✅ 4. DCL(Data Control Language)——控制访问权限
作用:管理数据库用户的访问权限(如登录、读写、管理),属于系统安全层。
核心命令:GRANT、REVOKE
特点:立即生效,不可回滚,通常由 DBA 执行。
📌 标准示例(带中文注释)
-- 1. 创建用户(生产环境使用专用账号,禁止用 root)
CREATE USER 'app_user'@'%' IDENTIFIED BY 'StrongPass123!';
-- 2. 授予用户对特定数据库的权限(最小权限原则!)
GRANT
SELECT, INSERT, UPDATE, DELETE
ON `order_system`.*
TO 'app_user'@'%';
-- 3. 授予特定表的权限(更细粒度)
GRANT SELECT ON `order_system`.`user` TO 'report_user'@'192.168.1.%';
-- 4. 撤销权限(权限变更时使用)
REVOKE DELETE ON `order_system`.`user` FROM 'app_user'@'%';
-- 5. 刷新权限(使变更立即生效)
FLUSH PRIVILEGES;
-- 6. 查看当前用户权限(调试用)
SHOW GRANTS FOR 'app_user'@'%';
✅ 企业最佳实践(DCL 规范)
| 规范项 | 说明 |
|---|---|
| 禁止 root | 应用程序连接数据库严禁使用 root 账号 |
| 最小权限 | 读写服务只授予 SELECT, INSERT, UPDATE, DELETE,禁止 DROP, CREATE |
| IP 限制 | 生产环境限制访问 IP,如 'app_user'@'10.0.1.%' |
| 密码强度 | 密码必须符合公司安全规范(大小写+数字+符号,长度≥12) |
| 权限审计 | 每季度审计一次用户权限,清理废弃账号 |
💡 Spring Boot 配置建议:
数据库连接账号使用app_user,密码通过 Vault / Nacos / 环境变量 注入,禁止写在配置文件中!
✅ 5. TCL(Transaction Control Language)——控制事务边界
作用:管理事务的提交、回滚、保存点,确保数据一致性。
核心命令:COMMIT、ROLLBACK、SAVEPOINT
特点:必须在事务中使用,通常由框架(如 Spring)自动管理。
📌 标准示例(带中文注释)
-- 1. 手动事务控制(仅用于调试或复杂逻辑,生产推荐用 @Transactional)
-- 开启事务(自动隐式开启,显式写法用于理解)
START TRANSACTION;
-- 执行多个操作(扣款 + 减库存)
UPDATE `account` SET `balance` = `balance` - 100 WHERE `user_id` = 1001;
UPDATE `inventory` SET `stock` = `stock` - 1 WHERE `product_id` = 2001;
-- ✅ 操作成功,提交事务(永久生效)
COMMIT;
-- ❌ 若中间出错,回滚事务(撤销所有操作)
-- ROLLBACK;
-- 2. 使用保存点(Savepoint)实现部分回滚(高级用法)
START TRANSACTION;
UPDATE `account` SET `balance` = `balance` - 50 WHERE `user_id` = 1001;
SAVEPOINT sp1; -- 设置保存点
UPDATE `inventory` SET `stock` = `stock` - 1 WHERE `product_id` = 2001;
-- 如果库存不足,回滚到 sp1,但保留扣款
-- ROLLBACK TO sp1;
-- 如果全部成功,提交
COMMIT;
-- 3. 设置自动提交模式(默认为 ON,生产不建议改)
-- 关闭自动提交(用于手动事务)
SET autocommit = 0;
-- 开启自动提交(默认模式,推荐)
SET autocommit = 1;
✅ 企业最佳实践(TCL 规范)
| 规范项 | 说明 |
|---|---|
| 禁止手动写 TCL | 生产代码中禁止直接写 COMMIT/ROLLBACK,应使用 @Transactional |
| 事务范围最小化 | 只包裹核心业务逻辑(如:扣款+减库存),不包裹远程调用、MQ 发送 |
| 事务超时设置 | Spring 中设置 @Transactional(timeout = 10),避免死锁 |
| 避免长事务 | 事务内不要执行耗时操作(如文件上传、HTTP 请求) |
| 隔离级别 | 默认 REPEATABLE READ,高并发场景可考虑 READ COMMITTED |
✅ Spring Boot 中的事务控制示例(Java 代码)
@Service
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.REPEATABLE_READ,
timeout = 10,
rollbackFor = Exception.class
)
public void transferMoney(Long fromUserId, Long toUserId, BigDecimal amount) {
// 扣款
accountService.debit(fromUserId, amount);
// 加款
accountService.credit(toUserId, amount);
// 若任意一步抛异常,事务自动回滚
// 不需要手动写 rollback!
}
✅ 团队约定:
所有涉及多表修改、资金操作、订单创建的方法,必须加@Transactional,否则视为严重缺陷!
三、SQL 分类总结对比表(快速查阅)
| 类别 | 命令 | 是否修改结构 | 是否修改数据 | 是否可回滚 | 典型场景 |
|---|---|---|---|---|---|
| DDL | CREATE, DROP, ALTER | ✅ 是 | ❌ 否 | ❌ 否 | 建表、加索引、改字段 |
| DML | INSERT, UPDATE, DELETE | ❌ 否 | ✅ 是 | ✅ 是 | 增删改用户、订单 |
| DQL | SELECT | ❌ 否 | ❌ 否 | ✅ 是(只读) | 查询用户、列表、报表 |
| DCL | GRANT, REVOKE | ❌ 否 | ❌ 否 | ❌ 否 | 设置用户权限 |
| TCL | COMMIT, ROLLBACK | ❌ 否 | ✅ 是 | ✅ 是(控制事务) | 保证事务一致性 |
四、推动团队落地的行动清单(可打印张贴)
| 动作 | 负责人 | 完成时间 |
|---|---|---|
| ✅ 统一发布《SQL 编写规范手册》 | 技术负责人 | 3天内 |
✅ 所有新表必须含 is_deleted, created_at, updated_at | 开发组 | 立即执行 |
| ✅ 所有 SQL 必须通过 Code Review(重点检查:是否用索引、是否逻辑删除) | Code Review 人员 | 持续进行 |
| ✅ 引入 SQL 审核工具(如:SonarQube + SQL Fluff) | DevOps | 2周内 |
| ✅ 每月一次“慢查询 & 无索引 SQL”复盘会 | DBA + 架构师 | 每月第一个周五 |
| ✅ 新人培训必须包含本指南内容 | 技术导师 | 新人入职第一周 |
五、附录:SQL 书写黄金法则(贴在工位)
🔹 写 SQL 前先问自己:
- 是否用了
SELECT *?→ 改成明确字段- 是否有
WHERE?→ 必须有,且用索引字段- 是否是物理删除?→ 改为
is_deleted = 1- 是否批量操作?→ 用
IN (...)或批量插入- 是否在事务中?→ 多表操作必须加
@Transactional- 是否用
EXPLAIN看过执行计划?→ 没看 = 不合格
✅ 结语:
SQL 不是“能跑就行”的脚本,而是系统稳定性的基石。
一条无索引的SELECT可拖垮整个数据库,一个忘记WHERE的UPDATE可摧毁用户数据。
请团队以写金融系统的心态,对待每一条 SQL。
MySQL SQL 分类企业级指南
22万+

被折叠的 条评论
为什么被折叠?



