ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MySQL学习笔记:DDL、DML、DQL三大SQL语句实战详解

MySQL学习笔记:DDL、DML、DQL三大SQL语句实战详解 整理了一份MySQL学习笔记正好写到3月4日这一版核心内容都集中在DDL、DML、DQL三类语句上。当时主要是想把数据库基础重新过一遍再用AI辅助方式加速理解结果发现把这三类语句吃透之后很多业务问题都变得清晰了比如订单查询怎么写、报表统计怎么优化、批量数据怎么安全更新。这篇文章我就把这版笔记重新梳理了一遍把当时做过的实验、踩过的坑、以及用AI当陪练的一些实际心得都放进来适合正在学MySQL的初学者也适合想快速复习SQL核心语法的开发者照着练习。1. 为什么三大类SQL语句是MySQL学习的骨架1.1 DDL/DML/DQL到底在说什么SQL语句按功能可以拆成好几类但日常开发里接触最多、也最能体现基本功的就是DDL、DML和DQL这三类。DDL全称是Data Definition Language负责定义数据结构DML全称是Data Manipulation Language负责操作数据本身DQL全称是Data Query Language负责查询数据。简单理解DDL是“盖房子”DML是“在房间里摆家具、换家具”DQL是“问房子里都有什么”。之所以说它们是骨架是因为无论你后面学事务、索引、存储过程、视图还是学主从复制、分库分表最终落到具体操作上都要靠这三类语句去完成。面试里考察手写SQL考的也几乎都是这三类。我见过不少同学一上来就研究存储引擎、事务隔离级别结果连建表语句都写不利索这种本末倒置的学习路径很容易让人卡住。还有一点需要说明SQL不只是MySQL独有Oracle、PostgreSQL、SQL Server也都有类似分类。把MySQL这三类语句练熟之后换到其他数据库时核心语法基本通用差别主要在数据类型、分页写法、函数名称这些细枝末节上。这也是我建议新手从MySQL入手的原因资料多、环境好搭、踩坑成本低。1.2 学习顺序和学习方法上的建议这三类语句的学习顺序我建议固定为DDL → DML → DQL。理由很简单你得先有一张表才能往里插入数据表里有了数据你查询才有意义。很多教程喜欢把查询单独拎出来讲结果新手对表结构还没有概念就直接面对一堆SELECT语句哪个字段来自哪张表都理不清越学越混乱。建议找一套完整的业务场景来练手比如“用户表 订单表 商品表”这种经典电商模型。哪怕是练习也要给自己设定业务约束用户手机号必须唯一订单金额不能为负数订单必须关联一个真实存在的用户。这样在练习DDL时会自然想到约束练习DML时会想到数据完整性练习DQL时才会有真实业务问题可以问。我的学习方法还有一个关键点手不要懒。看十遍语法不如自己敲一遍。练的时候不要用可视化工具的图形界面去建表直接在命令行或SQL编辑器里写语句这样你才会关注到每条语句的执行结果和报错信息。这类基础能力一旦扎实后面接触MyBatis、Flink CDC、Hive DDL这些生态工具时迁移成本非常低。2. DDL实战表结构设计才是基本功2.1 字段类型与约束的选择DDL里最核心的操作就是建表而行数和性能好不好在建表那一刻就已经决定了七八成。字段类型的选择我建议遵循“够用就好”的原则能放INT的不要放BIGINT能用VARCHAR(50)的不要给到VARCHAR(255)。类型越大占用的存储空间越多索引也会更大查询时扫描的页数也就越多这些都是隐性的性能成本。实操中比较常见的字段类型有这些我按使用频率列一下INT / BIGINT整数适合存自增主键、年龄、数量、状态值。VARCHAR(n)变长字符串适合存用户名、手机号、邮箱等长度不固定的文本。CHAR(n)定长字符串适合存固定长度的数据比如身份证号、订单号。DECIMAL(p,s)精确小数适合存金额、价格千万不可以用FLOAT/DOUBLE存钱。DATETIME / DATE时间和日期适合存创建时间、生日等。TEXT / LONGTEXT长文本适合存备注、文章内容但注意这类字段不能直接加普通索引。约束方面新手最容易漏的是复合业务规则。比如一个用户只能用一个手机号那就要在手机号字段上加UNIQUE约束金额字段必须大于等于0那就要加CHECK约束订单表里的用户ID必须存在于用户表那就要加外键。很多同学因为怕麻烦不写约束结果业务代码里各种判断最后还是会出现脏数据。2.2 从零写一条完整建表语句我用一个用户表来演示这个表看起来简单其实把常见知识点都涵盖了CREATE TABLE t_user ( id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 自增主键, username VARCHAR(50) NOT NULL COMMENT 用户名, mobile VARCHAR(20) NOT NULL COMMENT 手机号, email VARCHAR(100) DEFAULT NULL COMMENT 邮箱, status TINYINT NOT NULL DEFAULT 1 COMMENT 状态1启用 0禁用, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 更新时间, PRIMARY KEY (id), UNIQUE KEY uk_mobile (mobile), KEY idx_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_unicode_ci COMMENT用户表;几个细节我拆开说一下INT UNSIGNED表示无符号整数主键一般不会为负这样能让可表示的正数范围翻倍。AUTO_INCREMENT让主键自增不需要在插入时显式指定。DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP是MySQL 5.6.5之后支持的写法插入时自动写当前时间更新时自动刷新时间。UNIQUE KEY uk_mobile给手机号加唯一索引业务上保证一个手机号只能注册一个账号。字符集用utf8mb4而不是utf8因为utf8在MySQL里最多只支持3字节的字符存不了emoji和部分生僻字utf8mb4才是完整的4字节UTF-8编码。建表时不加COMMENT的表三个月后你就开始痛苦了。字段一多别人根本不知道这个字段是干什么的只能去翻代码。2.3 表结构修改与删除的实操细节表结构不是建好就不动了业务变化后经常要改字段。ALTER TABLE常用的几类操作分别是-- 增加字段 ALTER TABLE t_user ADD COLUMN nickname VARCHAR(50) DEFAULT NULL COMMENT 昵称; -- 修改字段类型 ALTER TABLE t_user MODIFY COLUMN username VARCHAR(64) NOT NULL COMMENT 用户名; -- 修改字段名 ALTER TABLE t_user CHANGE COLUMN mobile phone VARCHAR(20) NOT NULL COMMENT 手机号; -- 删除字段 ALTER TABLE t_user DROP COLUMN email; -- 增加索引 ALTER TABLE t_user ADD INDEX idx_status (status);这里有个很容易搞混的点MODIFY只能改字段类型和默认值改不了字段名CHANGE可以同时改字段名和字段类型。CHANGE后面要先写新字段名再写旧字段名和类型顺序写反直接报错。另外TRUNCATE TABLE和DROP TABLE的区别也要搞清楚。DROP TABLE是连表带结构整个删掉TRUNCATE TABLE是清空表中所有数据但保留表结构并且自增ID会重置。如果只是想删数据而保留表TRUNCATE的代价通常比DELETE小很多因为它是直接释放整个数据页不是逐行删除。不过生产环境里TRUNCATE要谨慎它不像DELETE配合WHERE条件可以精准删而是直接清空全部数据且无法在事务里通过ROLLBACK恢复操作之前必须确认这是你想要的效果。大表结构变更更要小心比如在百万行数据的表上新增字段虽然MySQL 5.6之后的INNODB_ALGORITHMINSTANT支持部分DDL操作秒级完成但并不是所有ALTER操作都能在线执行。修改主键、修改字符集这类操作会重建表生产环境必须评估低峰期再做并且先备份。实操上我习惯先把要执行的ALTER语句在测试库跑一遍统计耗时再决定是否在生产操作这比临时清空业务表安全得多。3. DML实战增删改要带着“后悔药”操作3.1 INSERT的几种姿势INSERT是DML里最温和的操作但写法上有不少讲究。最简单的就是单条插入INSERT INTO t_user (username, mobile, email) VALUES (zhangsan, 13812345678, zhangsanexample.com);注意我指定了字段名。如果不指定字段名就必须给所有非自增且非默认值的字段提供值这个顺序还要和表结构一致一旦表结构变了这种无字段名的INSERT大概率直接报错或把数据插错列。我建议不管字段多少都显式列出字段名清晰、稳定、可读性好。批量插入的写法要熟悉INSERT INTO t_user (username, mobile, email) VALUES (lisi, 13812345679, lisiexample.com), (wangwu, 13812345680, wangwuexample.com);批量插入的性能远高于循环单条插入因为每条INSERT都要经历一次SQL解析、事务提交和磁盘写入。用一条语句插多行MySQL内部可以优化成一次写入操作在数据导入、初始化测试数据这些场景里非常实用。还有一种组合写法是INSERT ... SELECT把查询结果直接插入另一张表比如把昨天之前注册的活跃用户复制到历史表一条语句搞定数据归档。注意这种写法要求SELECT出来的列数量和类型与INSERT的目标字段严格匹配不匹配就会报错或隐式转换出错。建议先把SELECT单独跑一遍确认结果集字段没问题再组合执行。3.2 UPDATE和DELETE必须养成的习惯UPDATE和DELETE是DML里风险最高的两类语句因为一旦写错WHERE条件后果是整个表的数据被改掉或清空。我见过真实生产事故排查问题的同学在测试环境想更新一条数据忘了在SQL前面加事务结果UPDATE语句把整张表的状态字段全部改成了错误的值最后只能从备份恢复。第一个习惯UPDATE和DELETE之前先SELECT确认WHERE条件匹配到的行数。-- 先查 SELECT * FROM t_user WHERE id 10086; -- 再改 UPDATE t_user SET status 0 WHERE id 10086;这个习惯看起来多了一步但能避免大量悲剧。哪怕只是多花5秒钟也值得养成。第二个习惯UPDATE和DELETE尽量加上LIMIT。MySQL没有单独的UPDATE LIMIT语法吗其实有比如UPDATE t_user SET status 0 WHERE status 1 LIMIT 100可以限制更新行数防止一次性更新百万行。DELETE同样支持LIMIT但要注意LIMIT值不要写错并且配合合适的WHERE条件使用而不是为了限制而限制。第三个习惯高危操作务必先在事务里执行确认无误再COMMIT。这个我放到下一节详细说因为事务就是DML操作的后悔药。还有一个细节DELETE FROM t_user WHERE id 10086如果没有索引MySQL会全表扫描定位这条记录在数据量大时非常慢。所以删除操作的时间复杂度受索引影响很大设计表结构时就该把高频WHERE条件对应的索引建好。3.3 事务机制给DML操作兜底InnoDB是MySQL默认的存储引擎也是支持事务的引擎。事务的ACID四个特性原子性、一致性、隔离性、持久性其中和DML操作关系最直接的就是原子性意思是一组SQL操作要么全部成功要么全部回滚不会出现只执行了一半的情况。实操中事务的使用方式如下START TRANSACTION; UPDATE t_account SET balance balance - 100 WHERE user_id 1; UPDATE t_account SET balance balance 100 WHERE user_id 2; -- 如果上面两条语句都执行成功 COMMIT; -- 如果某一条失败执行回滚 ROLLBACK;转账场景就是典型例子必须保证扣款和入账同时成功或同时失败。MySQL的默认提交模式是自动提交也就是每条语句单独一个事务但当我们手动执行START TRANSACTION之后后续语句就在同一个事务里了直到COMMIT或ROLLBACK。自动提交模式下还有个坑你在命令行或者客户端工具里执行UPDATE语句执行成功之后数据立刻永久写入没有后悔机会。这也是为什么我强调重要操作前最好显式开启事务养成这个习惯后你的DML操作会安全很多。事务使用要注意几个问题事务里不要做太多无关操作事务越大持有锁的时间越长并发性能越差。不要忘记COMMIT不提交的事务会一直持有锁其他会话对同一行的操作会被阻塞。ROLLBACK要谨慎使用如果事务里已经执行了几十万行UPDATE回滚也需要时间所以事务范围尽量控制在业务必需的最小集合。4. DQL实战查询是所有业务逻辑的出口4.1 WHERE过滤从全表扫描到精准匹配DQL是整个SQL里最考验逻辑能力的部分也是面试和工作中占比最大的部分。WHERE子句的作用是对表中的行进行过滤只有满足条件的行才会进入后续的排序、分组、连接等流程。基础运算符大家应该都熟悉、、、、、、BETWEEN AND、IN、LIKE。这里有一个新手经常忽略的点多个条件组合时AND的优先级比OR高。比如WHERE status 1 OR status 0 AND create_time 2026-01-01实际执行时会先计算AND部分结果和你想要的“两个状态都要且都要满足时间条件”完全不同。为了可读性和正确性复合条件务必用括号明确优先级WHERE (status 1 OR status 0) AND create_time 2026-01-01LIKE模糊查询也是高发问题点。LIKE %关键字%会导致全表扫描因为以通配符开头时索引无法有效利用。如果确实需要模糊搜索比如搜索用户名包含“张”的用户优先考虑LIKE 关键字%这种前缀匹配至少还能走索引的区间扫描。NULL的比较要特别注意IS NULL和IS NOT NULL用于NULL判断不能用 NULL或 NULL因为在SQL中NULL代表“未知”任何与NULL的直接比较结果都是NULLWHERE条件不会匹配到任何行。很多新手在这里莫名查不到数据就是被NULL坑了。4.2 排序、限量与分页ORDER BY用于排序语法上很简单但有几个点容易出错。多字段排序时排序字段的先后顺序决定优先级SELECT * FROM t_order ORDER BY status ASC, create_time DESC;这个语句先按status升序status相同再按create_time降序。如果要观察完整排序结果建议SELECT中带上排序字段否则肉眼很难确认排序是否按预期生效。LIMIT用于限制返回行数最常见的用法是分页SELECT * FROM t_order ORDER BY id DESC LIMIT 0, 20; -- 第1页 SELECT * FROM t_order ORDER BY id DESC LIMIT 20, 20; -- 第2页注意MySQL的LIMIT语法是LIMIT offset, sizeoffset从0开始不是1。如果写LIMIT 1, 20实际上是跳过第1行返回从第2行开始的20行新手经常在这里多一页或少一页。数据量大的时候深分页是大坑。比如LIMIT 1000000, 20MySQL会先扫描出1000020行然后丢掉前1000000行性能非常差。实用优化方案是记录上一页最后一条数据的ID用WHERE id 上一页最大ID ORDER BY id LIMIT 20来翻页这种基于游标的分页方式在千万级数据下性能稳定得多。不过这个写法只适用于按连续自增主键排序的场景。4.3 分组统计GROUP BY与HAVING分组统计是报表类需求的核心手段。GROUP BY按一个或多个字段把数据分组然后对每个组执行聚合计算常见聚合函数有COUNT、SUM、AVG、MAX、MIN。SELECT status, COUNT(*) AS cnt, SUM(order_amount) AS total_amount FROM t_order GROUP BY status;这条语句把订单表按状态分组统计每个状态的订单数量和订单总额是后台订单管理页的典型统计逻辑。WHERE和HAVING的执行顺序容易搞混WHERE是在分组之前对原始行进行过滤HAVING是在分组之后对聚合结果进行过滤。比如SELECT user_id, SUM(order_amount) AS total_amount FROM t_order WHERE order_status paid GROUP BY user_id HAVING total_amount 1000;这里先过滤已支付订单再按用户分组最后只保留消费总额超过1000的用户。如果想把“消费总额超过1000”放在WHERE里MySQL直接报错因为WHERE执行时SUM还没有计算出来。用生活场景类比WHERE就像去菜市场之前先把坏掉的菜挑掉HAVING是称好重量之后再决定是否装袋。另外要注意SELECT中出现的非聚合字段最好都出现在GROUP BY中。虽然MySQL有一个ONLY_FULL_GROUP_BY模式默认开启时会强制这个规则但如果你使用的环境关闭了这个模式查询结果可能会包含不确定的行这种“自由”反而是隐藏的地雷。4.4 多表连接JOIN的理解路径多表查询是对JOIN不理解的同学最容易卡壳的地方。JOIN的本质是笛卡尔积加上连接条件过滤两表连接时先把两表的每一行两两组合再根据ON条件筛出有效行。最常见的三种JOININNER JOIN只返回两表都满足条件的行。LEFT JOIN返回左表全部行右表没有匹配时填充NULL。RIGHT JOIN返回右表全部行左表没有匹配时填充NULL。我用一个简单场景演示用户表和订单表。SELECT u.username, o.order_id, o.amount FROM t_user u LEFT JOIN t_order o ON u.id o.user_id;这个查询会返回所有用户包括没有下过订单的用户订单字段为NULL。如果换成INNER JOIN就只返回至少有一个订单的用户了。实际业务中LEFT JOIN用得比较多因为通常需要以主表全量数据为准。JOIN查询里有一个容易忽视的细节ON子句的条件和WHERE子句的条件作用时机不同。以LEFT JOIN为例如果连接右表的条件写在WHERE里且这个条件排除了右表为NULL的行那LEFT JOIN的效果和INNER JOIN就没区别了。比如SELECT u.username, o.order_id FROM t_user u LEFT JOIN t_order o ON u.id o.user_id WHERE o.amount 100;这条语句会把右表为NULL的行过滤掉因为没有NULL能大于100于是无订单的用户被排除了。如果想要“所有用户以及他们超过100元的订单”过滤条件应该写在ON子句里SELECT u.username, o.order_id FROM t_user u LEFT JOIN t_order o ON u.id o.user_id AND o.amount 100;这个细节是面试高频考点也是实际写报表时常踩的坑。多表JOIN性能方面给连接字段和WHERE字段建索引可以显著降低嵌套循环匹配的代价没有索引时两张大表JOIN慢到让你怀疑MySQL是不是卡死了。4.5 子查询的适用场景与替代方案子查询是在一个SELECT里面嵌套另一个SELECT可以用在WHERE、FROM、SELECT列表等位置。最常见的是WHERE子查询SELECT username FROM t_user WHERE id IN ( SELECT DISTINCT user_id FROM t_order WHERE amount 500 );这个查询先找消费超过500元的用户ID集合再查这些用户的姓名。EXISTS子查询也是常见写法SELECT username FROM t_user u WHERE EXISTS ( SELECT 1 FROM t_order o WHERE o.user_id u.id AND o.amount 500 );EXISTS和IN在语义上非常接近但EXISTS更适合判断“是否存在”而且关联子查询通常可以用JOIN改写查询优化器可能生成更高效的执行计划。关于子查询和JOIN的选择有一个经验总结如果子查询结果集很小IN的性能通常不错如果子查询结果集很大或者需要对主表数据保留完整状态JOIN往往更优。还有一个细节是子查询中不要直接使用LIMIT尤其是MySQL版本较老时某些子查询中使用LIMIT会直接报错需要先包一层派生表。UPDATE中的子查询也比较实用比如把订单表中用户为VIP的金额打9折一条UPDATE配合子查询就能完成。这里要注意在MySQL里UPDATE同一张表时子查询不能直接引用目标表这时候需要把子查询再包一层临时表否则会报“You cant specify target table for update in FROM clause”的经典错误。5. 把AI变成你的SQL陪练5.1 用AI解释语法和执行计划2026年再学SQL手里不用AI确实是浪费。我自己的做法是把AI当成一个随时在线的陪练但绝不让它替我把所有SQL都写了因为AI写的SQL有时候看起来很对执行结果却和预期差一截。正确的使用方法一是让AI帮我解释执行计划二是让AI基于我的表结构生成练习场景三是让AI批改我写的SQL。执行计划对新手来说是陌生人但AI可以把输出结果翻译成大白话。在MySQL里先执行EXPLAIN SELECT * FROM t_user WHERE username zhangsan;然后把EXPLAIN的输出结果粘给AI让它解释type、key、rows这些字段代表什么顺便指出潜在问题。AI会告诉你比如type是ALL说明全表扫描建议在username上建索引。这种方法比自己翻文档高效很多能快速建立执行计划与实际性能之间的直觉。5.2 让AI生成练习题和对照语句AI可以按你的需求出SQL练习题。给它的提示词要具体比如这样给我设计一个MySQL练习场景有用户表、订单表、订单明细表三张表每张表至少5个字段包含主键、外键、索引。再出5道DQL练习题难度从基础到进阶要求覆盖JOIN、GROUP BY、HAVING、子查询。不要给我答案先让我自己写。AI会生成带建表语句的完整练习环境。我把建表语句在本地执行后把AI生成的练习题一道一道敲写完再让AI批改。批改时把表结构和我的SQL一起粘给它让它指出逻辑问题和性能隐患比单纯看标准答案要有价值得多。还有一种用法是让AI做“SQL改写”比如问它“这条查询用子查询写的能不能改成JOIN写法两种写法的执行计划有什么差异”这种改写练习能帮你理解不同SQL写法之间的等价关系在实际优化查询时非常有用。5.3 AI写SQL的三个注意点用了很长时间AI辅助SQL练习我总结出三个必须注意的点。第一AI会一本正经地输出错误SQL。尤其是多表JOIN和窗口函数组合时AI可能把字段别名写错、把ON条件写反甚至会默认一些MySQL并不支持的功能。所以AI生成的任何SQL都必须先自己读懂每一行逻辑再实际执行验证结果不要直接复制到生产环境。第二提示词里一定要带上表结构信息。如果你只问“帮我统计每个用户的订单总额”AI只能凭常识猜测字段名生成的结果大概率不匹配你的表。正确的做法是把建表语句、数据样例、期望结果都放进提示词AI才能给出可落地执行的SQL。第三AI再强也替代不了你对业务逻辑的确信度。我问过一个AI“UNION和UNION ALL有什么区别”它回答得很标准但换成一个实际场景“我们有个订单表已经被DROP了可以通过查询binlog恢复吗”这个就不是纯SQL语法问题了AI会给出模棱两可的答案你需要结合自己对MySQL日志体系的理解才能判断。我的最终建议把AI当搜索引擎加强版用它来理解概念、检查语法、生成练习题都很好但最终动手写SQL、优化SQL、排查数据问题的能力必须靠自己在命令行一遍遍敲出来。这类肌肉记忆是AI给不了你的。6. 实操中高频踩坑与排查速查6.1 最容易踩的5个SQL坑整理这版笔记时我把实际操作中踩过、或者教别人时见过的典型坑集中列一下UPDATE或DELETE漏掉WHERE导致全表数据被改或清空。解决办法是把“先SELECT再操作”当作强制习惯生产环境还可以加上SQL安全模式。NULL参与比较和运算结果不符合预期。比如WHERE mobile ! 13800000000不会返回mobile为NULL的行SUM(amount)会自动忽略NULL行如果你期望NULL按0处理就要用COALESCE(amount, 0)。字符串字段没引号直接写数字。MySQL有时会隐式转换比如WHERE mobile 13812345678虽然能执行但会导致索引失效。字符串比较必须加引号。字符集不一致导致乱码或查不出数据。表、字段、连接三者的字符集要统一为utf8mb4连接时可以用SET NAMES utf8mb4。数据类型隐式转换导致排序和比较出错。比如把VARCHAR字段按数字排序结果可能是1、10、100、2这种字符串排序效果需要在设计阶段就明确类型。这5个坑里前两个最容易引发生产事故。建议在练习环境里故意制造一次“忘记WHERE条件”的操作观察一下数据被批量改掉后的那种紧张感经历过一次你会彻底记住。6.2 环境配置与学习工具建议如果还没有本地MySQL环境这里给一点安装和配置方面的建议。MySQL 8.0是目前的主流版本安装方式有官方安装包、压缩包解压配置、RPM安装等。新手推荐用官方安装包图形化流程比较省心。配置上注意几点字符集选择utf8mb4root密码设置复杂一些不要使用系统默认的3306端口时记得在防火墙放行对应端口MySQL 8.0默认身份认证插件是caching_sha2_password部分老客户端连接会报SSL或认证错误如果遇到SSL connection error可以检查客户端驱动是否支持或暂时调整认证插件配置。学习工具方面我一向推荐先掌握命令行再使用图形化客户端。命令行能让你直面SQL的本质图形化客户端虽然方便但很容易让你停留在“点鼠标”层面建表、查数据都用向导完成语法反而记不住。当你在命令行能熟练完成建库、建表、增删改查后可以再使用DBeaver、Navicat或MySQL Workbench提升效率。DBeaver是开源免费的跨平台支持不错Navicat功能全面但收费。建议本地搭一套练习库不要只在线上空环境随手敲两句。练习库可以包含3-5张业务表自己模拟一些测试数据比如上文的用户表、订单表、商品表。平时练习时尽量开着慢查询日志把超过阈值的SQL捞出来看执行计划这是成本最低的SQL性能优化入门方式。6.3 一组常用SQL速查笔记最后部分我把DDL、DML、DQL里最高频的语句整理成一张速查方便你贴在手边操作类型场景语句模板DDL建库CREATE DATABASE db_name DEFAULT CHARACTER SET utf8mb4;DDL建表CREATE TABLE table_name (id INT PRIMARY KEY AUTO_INCREMENT, ...) ENGINEInnoDB;DDL加字段ALTER TABLE table_name ADD COLUMN col_name VARCHAR(50) DEFAULT NULL;DDL改字段ALTER TABLE table_name MODIFY COLUMN col_name INT NOT NULL;DDL删表DROP TABLE table_name;DML插单条INSERT INTO table_name (col1, col2) VALUES (v1, v2);DML插批量INSERT INTO table_name (col1, col2) VALUES (v1, v2), (v3, v4);DML更新UPDATE table_name SET col1 v1 WHERE id 10086;DML删除DELETE FROM table_name WHERE id 10086;DQL精准查询SELECT col1, col2 FROM table_name WHERE col1 value;DQL模糊查询SELECT * FROM table_name WHERE name LIKE keyword%;DQL排序分页SELECT * FROM table_name ORDER BY id DESC LIMIT 0, 20;DQL分组聚合SELECT status, COUNT(*), SUM(amount) FROM table_name GROUP BY status;DQL两表连接SELECT a.col, b.col FROM a LEFT JOIN b ON a.id b.a_id;DQL去重SELECT DISTINCT col1 FROM table_name;这张表不是让你背的而是当作索引。哪天忘了某个写法扫一眼就能回忆起结构再去翻完整语法文档或让AI展开补充细节效率比自己翻书高很多。从3月4日整理笔记到现在我再回头看最大的感受是DDL、DML、DQL并不是三个孤立的语法块它们是一套完整的数据操作逻辑。DDL决定数据长什么样DML决定数据如何变化DQL决定数据如何被使用三者合在一起才是你在数据库层面表达业务的能力。AI在这中间确实帮了大忙但真正让这些语法内化成自己能力的还是那一次次在命令行里敲出来的实操。踩过几次坑之后你自然会发现SQL基础扎实了后面无论是学存储过程、触发器还是上手大数据生态里的Hive、Flink、ClickHouse都会顺畅很多。
返回列表