当前位置: 首页 > news >正文

MySQL 的 DDL / DML / DQL / DCL 做一次系统梳理:概念区别→常用语法→特点与注意点→实战小例子→常见面试/坑点速记

一、四大类的定位(先看这张速查表)

类别全称主要作用典型语句是否改动数据是否改动结构事务性权限相关
DDLData Definition Language定义/变更数据库对象结构CREATE / ALTER / DROP / RENAME / TRUNCATE否(但会影响数据存在形态,TRUNCATE 会清空)有些操作可原子化(8.0起部分原子DDL),通常自动提交
DMLData Manipulation Language新增/修改/删除数据INSERT / UPDATE / DELETE / REPLACE支持事务
DQLData Query Language查询数据SELECT(含 JOIN/GROUP BY/HAVING/WINDOW 等)参与事务一致性(快照读/锁定读)
DCLData Control Language账户、权限与角色控制CREATE USER / GRANT / REVOKE / DROP USER / CREATE ROLE不涉及业务事务

另外常见还有 TCL(Transaction Control Language)START TRANSACTION / COMMIT / ROLLBACK / SAVEPOINT / SET TRANSACTION,配合 DML 使用。


二、DDL(定义结构)

1)创建库/表

-- 创建数据库
CREATE DATABASE IF NOT EXISTS shopDEFAULT CHARACTER SET utf8mb4DEFAULT COLLATE utf8mb4_0900_ai_ci;-- 创建表(InnoDB、主键、自增、唯一索引、外键)
CREATE TABLE IF NOT EXISTS shop.user (id        BIGINT PRIMARY KEY AUTO_INCREMENT,username  VARCHAR(50) NOT NULL UNIQUE,email     VARCHAR(100),created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB;-- 订单表,外键参照 user(id)
CREATE TABLE shop.orders (id        BIGINT PRIMARY KEY AUTO_INCREMENT,user_id   BIGINT NOT NULL,amount    DECIMAL(10,2) NOT NULL,status    ENUM('PENDING','PAID','CANCELLED') NOT NULL DEFAULT 'PENDING',created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,CONSTRAINT fk_orders_userFOREIGN KEY (user_id) REFERENCES shop.user(id)ON UPDATE CASCADEON DELETE RESTRICT
) ENGINE=InnoDB;

2)修改、删除结构

-- 增加列 / 修改列类型 / 重命名列
ALTER TABLE shop.user ADD COLUMN phone VARCHAR(20) AFTER email;
ALTER TABLE shop.user MODIFY COLUMN phone VARCHAR(30);
ALTER TABLE shop.user RENAME COLUMN phone TO mobile;-- 索引:创建/删除(也可写在 ALTER TABLE 中)
CREATE INDEX idx_orders_userid ON shop.orders(user_id);
DROP INDEX idx_orders_userid ON shop.orders;-- 重命名表 / 删除表 / 清空表
RENAME TABLE shop.orders TO shop.order_main;
DROP TABLE IF EXISTS shop.order_main;
TRUNCATE TABLE shop.user; -- 清空数据、重置自增,速度快,DDL 语句

DDL 特点与注意

  • 自动提交:DDL 通常隐式提交事务,不会被后续 ROLLBACK 回滚。

  • 元数据锁(MDL)ALTER/CREATE/DROP 会对表加 MDL,可能阻塞业务。

  • TRUNCATE vs DELETETRUNCATE 是 DDL,清空全表、重置自增、不可逐行触发触发器;DELETE 是 DML,可带 WHERE、可回滚(在事务中)。

  • 字符集:MySQL 8.x 推荐 utf8mb4;避免历史 utf8(不完整)。


三、DML(操作数据)

1)INSERT(含批量、插入或更新)

-- 单行/多行插入
INSERT INTO shop.user (username, email) VALUES('alice', 'alice@x.com'),('bob', 'bob@x.com');-- 基于查询插入
INSERT INTO shop.orders (user_id, amount, status)
SELECT id, 99.99, 'PENDING' FROM shop.user WHERE username='alice';-- Upsert:主键/唯一键冲突时更新(MySQL 常用)
INSERT INTO shop.user (id, username, email)
VALUES (1, 'alice', 'a@x.com')
ON DUPLICATE KEY UPDATE email = VALUES(email), updated_at = CURRENT_TIMESTAMP;-- 插入忽略错误(如唯一键冲突直接跳过)
INSERT IGNORE INTO shop.user (username, email) VALUES ('alice', 'dup@x.com');

2)UPDATE / DELETE

-- 更新
UPDATE shop.user
SET email='alice_new@x.com'
WHERE username='alice';-- 带 JOIN 的更新(MySQL 支持)
UPDATE shop.orders o
JOIN shop.user u ON o.user_id = u.id
SET o.status='CANCELLED'
WHERE u.username='bob';-- 删除:务必加 WHERE,结合事务
DELETE FROM shop.orders WHERE status='CANCELLED' AND created_at < NOW() - INTERVAL 30 DAY;

3)REPLACE(MySQL 特有)

-- 如果存在相同主键/唯一键记录:先删后插;否则直接插
REPLACE INTO shop.user (id, username, email) VALUES (1, 'alice', 're@x.com');

DML 特点与注意

  • 事务支持(InnoDB):用 START TRANSACTION ... COMMIT/ROLLBACK 保证原子性。

  • 批量写入:合并多行 INSERT 明显快于逐行。

  • UpsertINSERT ... ON DUPLICATE KEY UPDATE 优于先查后更;REPLACE删除重建(触发删除副作用)。

  • 安全更新模式:某些客户端默认不允许无条件 UPDATE/DELETE;建议总是加 WHERELIMIT(如果语义允许)。


四、DQL(查询数据)

1)基础查询

-- 投影/过滤/排序/分页
SELECT id, username, email
FROM shop.user
WHERE email LIKE '%@x.com'
ORDER BY id DESC
LIMIT 10 OFFSET 0;

2)聚合与分组

SELECT u.id, u.username, COUNT(o.id) AS order_cnt, SUM(o.amount) AS total_amount
FROM shop.user u
LEFT JOIN shop.orders o ON o.user_id = u.id AND o.status='PAID'
GROUP BY u.id, u.username
HAVING COUNT(o.id) > 0
ORDER BY total_amount DESC;

3)子查询 / CTE(8.0+)

-- 子查询
SELECT * FROM shop.user
WHERE id IN (SELECT user_id FROM shop.orders WHERE amount > 100);-- CTE(WITH)可读性更好
WITH big_order AS (SELECT user_id, amount FROM shop.orders WHERE amount > 100
)
SELECT u.username, b.amount
FROM shop.user u
JOIN big_order b ON b.user_id = u.id;

4)窗口函数(8.0+)

-- 计算每个用户订单累积金额与序号
SELECTo.id, o.user_id, o.amount,SUM(o.amount) OVER (PARTITION BY o.user_id ORDER BY o.created_at) AS running_total,ROW_NUMBER() OVER (PARTITION BY o.user_id ORDER BY o.amount DESC) AS rn
FROM shop.orders o;

5)一致性与锁

  • 快照读:普通 SELECT 读取一致性视图,不加锁。

  • 锁定读SELECT ... FOR UPDATE / LOCK IN SHARE MODE 会加行锁,常用于事务内检查后再修改。

  • EXPLAIN:优化查询前先 EXPLAIN 看执行计划;必要时建索引或调整 SQL。


五、DCL(账户、权限、角色)

1)账户与密码

-- 创建用户(限制来源主机)
CREATE USER 'reporter'@'%' IDENTIFIED BY 'StrongP@ssw0rd';-- 修改密码 / 失效
ALTER USER 'reporter'@'%' IDENTIFIED BY 'StrongerP@ss1';
DROP USER 'reporter'@'%';

2)授权与回收

-- 授权(最小权限原则)
GRANT SELECT ON shop.* TO 'reporter'@'%';
GRANT SELECT, INSERT, UPDATE, DELETE ON shop.orders TO 'reporter'@'%';-- 查看与回收
SHOW GRANTS FOR 'reporter'@'%';
REVOKE INSERT, UPDATE, DELETE ON shop.orders FROM 'reporter'@'%';

3)角色(8.0+)

CREATE ROLE 'read_only';
GRANT SELECT ON shop.* TO 'read_only';
GRANT 'read_only' TO 'reporter'@'%';
SET DEFAULT ROLE 'read_only' TO 'reporter'@'%';

说明:MySQL 8 起支持动态权限(如 REPLICATION SLAVE ADMIN 等),用于管理运维功能;常见业务中以对象级(库/表/列/过程)权限为主。


六、TCL(事务控制,配合 DML)

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; -- MySQL 默认START TRANSACTION;UPDATE shop.orders SET status='PAID' WHERE id=1001;SAVEPOINT s1;UPDATE shop.user SET email='oops@x.com' WHERE id=1;ROLLBACK TO s1; -- 撤销误操作
COMMIT;

要点

  • 尽量短事务,避免长时间持锁。

  • 明确隔离级别对“幻读/不可重复读”的影响;需要强一致时用 SELECT ... FOR UPDATE


七、典型对比与坑点速记

  1. DROP vs TRUNCATE vs DELETE

  • DROP TABLE:删表定义+数据,结构直接没了。

  • TRUNCATE TABLE:清空数据、重置自增,快,不可逐行回滚/触发器。

  • DELETE FROM t:逐行删除,可加 WHERE,在事务内可回滚。

  1. INSERT 冲突处理

  • INSERT ... ON DUPLICATE KEY UPDATE(推荐)

  • REPLACE INTO:实际是删后重插,可能触发“删除副作用”。

  1. 索引

  • where/join/order by/group by 的列要评估索引;避免函数包裹导致索引失效(如 WHERE DATE(created_at)=...)。

  • 组合索引遵循最左前缀

  1. 外键

  • 需要事务型引擎 InnoDB;明确 ON DELETE/UPDATE CASCADE|RESTRICT|SET NULL 语义。

  • 大吞吐写场景要评估外键带来的约束检查成本。

  1. 字符集与排序规则

  • 统一 utf8mb4,跨库/表/连接保持一致,避免“问号/乱码”。

  1. 原子 DDL(8.0+)

  • 部分 DDL 具备原子性(失败自动回滚元数据),但依旧会隐式提交,不能当普通事务使用。


八、从零到一:小实战脚本(可直接粘贴)

-- 1. 结构(DDL)
CREATE DATABASE IF NOT EXISTS demo DEFAULT CHARACTER SET utf8mb4;
USE demo;CREATE TABLE user (id BIGINT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL UNIQUE,email VARCHAR(100),created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;CREATE TABLE orders (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT NOT NULL,amount DECIMAL(10,2) NOT NULL,status ENUM('PENDING','PAID','CANCELLED') NOT NULL DEFAULT 'PENDING',created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,CONSTRAINT fk_orders_user FOREIGN KEY (user_id) REFERENCES user(id)
) ENGINE=InnoDB;CREATE INDEX idx_orders_userid ON orders(user_id);-- 2. 数据(DML)
INSERT INTO user (username, email) VALUES('alice', 'alice@x.com'),('bob', 'bob@x.com');INSERT INTO orders (user_id, amount, status)
SELECT id, 128.88, 'PAID' FROM user WHERE username='alice';-- 3. 查询(DQL)
SELECT u.username, COUNT(o.id) AS cnt, SUM(o.amount) AS total
FROM user u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.username
HAVING total IS NOT NULL
ORDER BY total DESC;-- 4. 权限(DCL)
CREATE USER 'reporter'@'%' IDENTIFIED BY 'StrongP@ss';
GRANT SELECT ON demo.* TO 'reporter'@'%';


九、记忆

  • 改结构用 DDL;

  • 改数据用 DML;

  • 查数据是 DQL;

  • 管权限用 DCL;

  • 管事务用 TCL。

  • 安全与性能两条线:权限最小化(DCL)、索引+EXPLAIN(DQL)、短事务(TCL)、避免无 WHERE 的批量 DML

  • 面试常问:DELETE vs TRUNCATE vs DROPON DUPLICATE KEY UPDATE事务隔离级别最左前缀原则SELECT ... FOR UPDATE 场景。

http://www.dtcms.com/a/335321.html

相关文章:

  • 解构下一-代 AI 智能体:超越 LLM,深度解析三大核心支柱——上下文、认知与行动
  • 基础数据结构
  • Linux——进程管理和计划任务管理
  • Python中*args和**kwargs
  • 基于springboot的在线视频教育管理系统设计与实现(源码+文档+部署讲解)
  • Flow-GRPO:通过在线 RL 训练 Flow matching 模型
  • 概率论基础教程第3章条件概率与独立性(二)
  • 如何解决C盘存储空间被占的问题,请看本文
  • C语言零基础第18讲:自定义类型—结构体
  • 9.从零开始写LINUX内核——设置中断描述符表
  • duiLib 实现鼠标拖动标题栏时,窗口跟着拖动
  • 深入了解 swap:作用、局限与分区建立
  • Linux sar命令详细使用指南
  • Effective C++ 条款45:运用成员函数模板接受所有兼容类型
  • Day2--滑动窗口与双指针--2090. 半径为 k 的子数组平均值,2379. 得到 K 个黑块的最少涂色次数,2841. 几乎唯一子数组的最大和
  • Linux软件编程:线程间通信
  • 【FreeRTOS】队列集
  • MySQL 插入数据提示字段超出范围?一招解决 DECIMAL 类型踩坑
  • 第三十七天(js前端数据加密和混淆)
  • Fixture Caliper 工具
  • GRPO(Group Relative Policy Optimization)公式速览
  • Scala面试题及详细答案100道(11-20)-- 函数式编程基础
  • 嵌入式软件架构设计之九: 双机通信之通信方式
  • 排列与组合
  • 超详细yolov8/11-obb旋转框全流程概述:配置环境、数据标注、训练、验证/预测、onnx部署(c++/python)详解
  • STM32标准库学习笔记
  • MM-Spatial和Spatial-MLLM论文解读
  • 【力扣-多数元素 JAVA/Python】
  • CD4+ T细胞激活区分抗PD-L1联合抗CTLA4疗法与单药抗PD-L1治疗的响应差异-空间最近邻分析
  • 民法学学习笔记(个人向) Part.5