恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

SQL基础教程PDF全解析:从建表到索引优化与事务实践

  • 首页
  • 资讯中心
  • /
  • SQL基础教程PDF全解析:从建表到索引优化与事务实践

相关资讯

服务端与客户端职责边界:信任边界与能力边界的双重切割 2026/10/9 22:39:32
Matplotlib堆积图实战:从数据准备到自动化出图的完整指南 2026/10/9 22:39:32
Python与MySQL学生选课管理系统:数据库设计到实现与答辩 2026/10/9 22:39:32

最新资讯

数据库大作业:基于Python酒店管理系统的表设计与避坑指南
从竞赛大神到桌游设计者:拆解楼教主的成长路径与竞赛方法论
Cursor 免费试用额度没了?把 Base URL 改到 TaoToken 的排查记录
【现代声明式UI学与练】第2课 声明式UI的实际载体和三种载体形态深度解析
基于YOLO的人群计数实现:从密度图回归到推理后处理全链路改造指南
Codex 真香!终端 AI 编程神器装好了,Cursor 可以不续费了:TaoToken 统一 Key 接入实测

今日推荐

AI编程智能体实战:从写代码到指挥代码的架构与落地
多模态大模型全栈能力拆解:从数据对齐到弹性推理
大模型Agent开发入门:从工具调用循环到落地避坑指南

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

SQL基础教程PDF全解析:从建表到索引优化与事务实践

发布时间:2026/10/9 22:44:33
SQL基础教程PDF全解析:从建表到索引优化与事务实践 简介这是一份面向数据库初学者的SQL基础教程PDF系统讲解结构化查询语言的核心概念与常用语法。内容涵盖数据库表结构、SELECT语句及结果集、SELECT DISTINCT去重、UPDATE更新、DELETE删除、INSERT INTO插入同时完整列出数据操作语言DML与数据定义语言DDL的主要语句如CREATE TABLE、DROP TABLE、CREATE INDEX等还特别强调了SQL大小写不敏感和分号使用规范帮助读者从零掌握SQL管理与操作关系型数据库的基本技能。资源以单个PDF文件形式打包大小约305KB纯文档格式便于阅读与检索。目前已有425人学习下载适合需要快速入门SQL、准备数据库相关课程或复习基础语法的学习者。教程配有丰富的实例与结果集展示直观呈现每条语句的执行效果能有效降低初学者的理解门槛是一份简洁实用的SQL入门参考资料。1. SQL基础教程这份PDF为什么值得从头到尾啃一遍如果你写SQL还是靠记忆片段拼凑、遇到多表查询就抓瞎那这份完整版SQL基础教程PDF值得从头到尾过一遍。它不像那些只讲单表增删改查的入门笔记而是把DLL、DML、数据查询、多表联结、索引、事务这些分散的知识点串成一条完整的进阶主线覆盖了实际开发和数据分析里九成以上的SQL场景。适合刚接触数据库的新手作为第一份系统读物也适合已经在用但基础不牢的工作者用它把知识漏洞补上。这个资源拿到手之后建议按章节顺序学而不是当成字典随处查。真正把这些知识点连起来你会发现之前的很多写法都只是在碰运气。下面先拆解这份PDF的内容结构再说怎么把它变成自己的技能以及最容易翻车的地方在哪里。2. 拆解教程体系从建表到查询优化的主线与副线2.1 前八章的语法主干DDL、DML与单表查询任何SQL学习资料的第一部分都是建库建表和数据操纵这份PDF也不例外但它的编排比很多教程更合理。前几章先讲清楚CREATE TABLE、ALTER TABLE、DROP TABLE这类DDL语句再进入INSERT、UPDATE、DELETE这些DML操作最后才是SELECT查询。这个顺序之所以合理是因为SELECT虽然是日常用得最多的语句但它依赖表结构和数据存在先建表再插数据再查询每一步都能在本地环境里得到验证不会有“看懂了但不知道去哪练”的困扰。在DDL部分PDF重点讲解了数据类型的选择和约束条件的设置。INT、VARCHAR、DECIMAL、DATE这些基础类型该怎么选PRIMARY KEY和FOREIGN KEY约束什么时候加这些内容看起来很基础但实际工作中很多查询慢或者数据错乱的问题根源都在建表阶段选错了类型或者漏加了约束。比如价格字段如果用了FLOAT而不是DECIMAL经过多轮累计运算之后会出现精度漂移对账就是对不平这种问题一旦发生事后修数据的成本远高于建表时多花两分钟选对类型。DML部分则值得注意它对事务概念的提前引入。初学者容易觉得INSERT就是一锤子买卖插完就完了但PDF在UPDATE和DELETE章节就铺垫了事务的原子性概念——要么全部成功要么全部回滚。这个铺垫很重要因为等到后面学事务隔离级别的时候你不会觉得那是凭空冒出来的新知识而是对前面行为的深层解释。跟着这部分的例子执行一遍对数据操作的基本功会有比较扎实的把握。单表查询部分是整份PDF的重头戏之一。SELECT的语法顺序和执行顺序在这里交代得很清楚写法上是SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY但实际执行顺序是FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY。新手最容易踩的坑就是把别名用在WHERE里而PDF在这个地方专门做了对比说明告诉你为什么WHERE里用不了SELECT里定义的别名必须先算完WHERE才能轮到SELECT。这个点说出来不值钱但自己悟可能要折腾不少时间。2.2 中段进阶多表联结、子查询与聚合配合过了单表查询就是很多人开始放弃的地方——多表联结。PDF把INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN放在一起讲并且用同一组业务数据做演示让读者直观看到不同JOIN类型返回的行数差异。这个设计比较贴心因为只看定义背概念很容易忘但看到同一张员工表分别用LEFT JOIN和INNER JOIN去关联部门表得到不同结果时联结逻辑就自然内化了。联结之外PDF用了一整章来讲子查询包括WHERE子查询、FROM子查询和SELECT子查询。其中标量子查询和关联子查询的对比是这一章的精髓普通子查询独立运行一次而关联子查询会随着外层每一行数据的流动反复执行。PDF用“查每个部门中工资最高的员工”这个经典问题来演示关联子查询的写法并解释为什么需要别名来区分内外层同名字段。这个案例虽然老但确实是最能说明关联子查询执行机制的例子。聚合函数和GROUP BY的配合也被单独成章重点在于HAVING和WHERE的分工。WHERE筛选的是分组前的行HAVING筛选的是分组后的聚合结果条件里如果出现COUNT、SUM这类聚合函数就只能放进HAVING。PDF用一组销售订单数据演示了不同写法得到的不同统计口径看完之后你对“分组”这个概念的理解会比碎片化自学清晰很多。2.3 后半部分的价值索引、事务与SQL思维这份PDF比大多数基础教程多出来的部分是索引和事务这两章。很多入门书讲到查询就结束了但这本把性能问题也纳入了“基础”的范畴。索引章节解释了聚簇索引和非聚簇索引的区别、联合索引的最左前缀原则以及为什么不要在索引列上做函数运算。这些东西在面试中反复出现在工作中也确实影响查询性能PDF把它们放在基础部分等于提前帮你建立了性能意识。事务章节覆盖了ACID四个特性和四种隔离级别READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ、SERIALIZABLE。每种隔离级别对应的脏读、不可重复读、幻读问题PDF用表格做了对比这个对比表在复习时价值很高比重新翻正文效率高得多。PDF最后还补了一个部分讲SQL思维强调先想清楚结果集长什么样再动手写语句。这个习惯建议尽早养成。很多人在写复杂报表查询时是先写一句SELECT *再慢慢拼JOIN和WHERE最后发现结果和预期差很多来回调试半天。如果动笔前先在注释里写出目标结果的行数和列含义写起来会顺畅很多。这份PDF在思维层面给的建议不多但每一条都值得反复揣摩。3. 照单练习把PDF里的例子改成自己的SQL语句3.1 准备一个本地练习环境看PDF和动手写SQL是两码事前者只能建立认知后者才会形成手感。建议花10分钟搭建一个本地练习环境后面所有的章节例子都亲手跑一遍。最常见的搭配是MySQL加一个图形化客户端MySQL本身免费下载安装后在终端里启动服务再用命令行或图形客户端连上去就可以操作了。如果你在某个云平台已经开过数据库实例那直接用线上的也行只是要注意别把练习用的测试数据建在正式业务的库里。创建一个练习专用的数据库推荐命名为practice_db后续所有练习都在这一个库里进行避免把测试数据散落在多个库里不好清理。SQL语句如下-- 创建练习数据库指定UTF8字符集避免中文乱码 CREATE DATABASE IF NOT EXISTS practice_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 切换到该数据库 USE practice_db;这段代码里的IF NOT EXISTS可以在数据库已存在时跳过创建步骤避免重复执行时报错。DEFAULT CHARACTER SET utf8mb4则是明确指定字符集utf8mb4支持Emoji和大部分生僻字比老的utf8兼容性更好。COLLATE指定排序规则utf8mb4_general_ci在多数场景下够用如果你需要大小写敏感的比较再换成utf8mb4_bin。3.2 从SELECT到JOIN的落地写法有了环境接下来把PDF里最核心的查询案例自己实现一遍。先建两张简单的表一张是员工表一张是部门表然后演示JOIN的用法。为什么用这两张表因为员工和部门是多对一关系这种关系最能体现JOIN的应用场景而且结果集直观错没错一眼就能看出来。-- 创建部门表 CREATE TABLE IF NOT EXISTS dept ( dept_id INT PRIMARY KEY, dept_name VARCHAR(50) NOT NULL ); -- 创建员工表部门ID作为外键关联部门表 CREATE TABLE IF NOT EXISTS emp ( emp_id INT PRIMARY KEY, emp_name VARCHAR(50) NOT NULL, salary DECIMAL(10, 2), dept_id INT, CONSTRAINT fk_dept FOREIGN KEY (dept_id) REFERENCES dept(dept_id) ); -- 插入部门数据 INSERT INTO dept (dept_id, dept_name) VALUES (1, 技术部), (2, 市场部), (3, 人事部); -- 插入员工数据 INSERT INTO emp (emp_id, emp_name, salary, dept_id) VALUES (101, 张三, 12000, 1), (102, 李四, 9000, 1), (103, 王五, 8000, 2), (104, 赵六, NULL, NULL);建表语句中DECIMAL(10,2)用来存薪资10位有效数字、小数点后两位避免浮点误差。外键约束在练习环境里可以帮你养成好习惯但在实际生产环境中很多团队为了写入性能会故意不用外键改由应用层保证数据一致性这个取舍你在读完PDF的事务章节之后会有更深的理解。接下来分别执行LEFT JOIN和INNER JOIN-- 内联结只保留两边都匹配上的行 SELECT e.emp_name, e.salary, d.dept_name FROM emp e INNER JOIN dept d ON e.dept_id d.dept_id; -- 左联结保留员工表全部行没有匹配的部门显示NULL SELECT e.emp_name, e.salary, d.dept_name FROM emp e LEFT JOIN dept d ON e.dept_id d.dept_id;这两个查询的关键差异在结果集行数上。员工表里赵六的dept_id是NULLINNER JOIN会把他过滤掉LEFT JOIN则会保留他并把部门名显示为NULL。PDF在这里给的建议是先想清楚业务上需不需要保留未匹配的行再决定用哪种JOIN不要无脑LEFT JOIN。这个建议在实际需求分析中非常实用比如统计离职员工历史数据时就需要LEFT JOIN保留那些已经不在部门表里的员工。3.3 子查询与GROUP BY的组合认知JOIN熟练之后下一步是把子查询和聚合函数组合起来用。PDF里那个“查每个部门工资最高员工”的经典案例是检验你是否真正理解关联子查询的试金石-- 关联子查询每个部门中工资最高的员工 SELECT e.emp_name, e.salary, e.dept_id FROM emp e WHERE e.salary ( SELECT MAX(salary) FROM emp WHERE dept_id e.dept_id );这段代码的执行逻辑是外层每取到一行员工记录就把它的dept_id传给内层子查询算出这个部门最高的工资再与外层当前行的salary比较。注意内层WHERE里的dept_id没有加表别名它和外层的e.dept_id引用的是同一个字段正是因为内层表和外层表是同名表的自关联别名e才是区分内外层的关键。如果漏了别名MySQL会直接报错说字段不明确这个报错信息其实是很好的提示。GROUP BY与HAVING的组合可以模拟一个按部门统计平均工资的场景-- 按部门分组过滤出平均工资低于10000的部门 SELECT dept_id, AVG(salary) AS avg_salary, COUNT(*) AS emp_count FROM emp GROUP BY dept_id HAVING AVG(salary) 10000;这里AVG(salary)会忽略NULL值也就是赵六那条salary为NULL的记录不会参与平均值计算。COUNT(*)则不同它统计的是行数哪怕某行所有字段都是NULL也会被计数。想统计有效薪资记录数的话应该用COUNT(salary)。这个区别是SQL新手最容易忽略的细节建议亲手验证一下结果差异比死记定义有用得多。4. 从看得懂到写得好索引、执行计划与事务收尾4.1 用EXPLAIN看执行计划别让SQL变成黑匣子只满足于“查询能跑出结果”是不够的SQL写得好不好要用EXPLAIN来验证。EXPLAIN是MySQL提供的一条诊断语句放在SELECT前面执行就能看到查询的执行计划。PDF的索引章节虽然解释了索引的原理但真正把原理和实际查询连起来的工具就是EXPLAIN。我在工作中遇到查询慢的问题第一步永远是EXPLAIN看执行计划而不是凭感觉加索引。-- 查看一条查询的执行计划 EXPLAIN SELECT e.emp_name, d.dept_name FROM emp e LEFT JOIN dept d ON e.dept_id d.dept_id WHERE e.salary 8000;执行计划里重点看几个字段type列展示访问类型从好到差依次是const、eq_ref、ref、range、index、ALL。ALL代表全表扫描数据量大了就非常慢。key列显示实际用到的索引名rows列是预估扫描的行数。如果type是ALL而且rows的数字接近全表行数这说明查询没有走索引需要检查WHERE条件字段是否有索引或者查询写法是否破坏了索引生效的条件。4.2 索引选择的三个实用原则PDF的索引章节给出的理论在这里落到实践上第一为WHERE和JOIN字段建索引这是最直接有效的场景。第二不要在索引列上做表达式运算或函数处理比如WHERE salary * 1.1 10000这个写法MySQL很难利用salary字段上的普通索引因为每一行都需要先算完乘法再比较索引无法直接定位。改成WHERE salary 10000 / 1.1就能走索引。第三联合索引要遵守最左前缀原则索引建在(a, b, c)三个字段上查询条件里没用到a那b和c也用不上索引。这三种情况可以用一句话概括索引是给查询优化器指路的你把路标弄模糊了优化器就只能按原路摸。4.3 事务隔离级别的取舍逻辑事务章节的隔离级别不是概念背诵题而是有明确取舍逻辑的工程决策。RR隔离级别下一个事务内多次读取同一记录的结果一致但并发写时会出现间隙锁问题可能影响写入吞吐量。RC隔离级别下不可重复读是允许的但写入并发能力比RR要好。选择哪个级别取决于业务对一致性的容忍度。-- 查看当前事务隔离级别 SELECT transaction_isolation; -- 修改当前会话的事务隔离级别 SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;对应到这个练习库里如果把隔离级别从RR改成RC然后开两个命令行窗口模拟两个事务同时读写同一行你会发现脏读、不可重复读的表现和PDF表格里描述完全一致。亲手验证一次之后你对隔离级别的理解就不再是死记硬背了。我一般会在做完这些练习之后把PDF的索引和事务两章再读一遍这次读的时候体会完全不同前者提供概念框架后者填补实操验证过的细节。5. 常见问题与避坑按现象、原因、解决来对照5.1 跟着PDF抄代码却查不出数据现象原样执行PDF里的查询语句结果集为空但表里分明是有数据的。原因最常见的是当前使用的数据库和建表所在库不是同一个或者表名大小写与库中实际名称不一致。MySQL在Linux下对表名大小写敏感在Windows下默认不敏感跨平台切换环境就容易踩这个坑。另一个原因是字符串比较时中文编码不一致表中存储的中文是gbk插入的查询条件里写的是utf8编码的中文字面上一样但底层字节串不同自然匹配不上。解决先执行SELECT DATABASE()确认当前库名再SHOW TABLES查看表名。匹配不到数据时用HEX()函数查看字段的十六进制值看看存储的到底是不是你以为的那些字符。中文乱码问题从源头解决建库统一用utf8mb4客户端连接也设置SET NAMES utf8mb4。5.2 用了LEFT JOIN结果行数翻倍现象两张表关联查询后结果行数比左表行数多出很多数据看起来像被“复制”了。原因左表的一行在右表中有多个匹配行。比如emp表和project表关联一个员工名下挂了多个项目LEFT JOIN会把每个项目都拼成一行左表一行就变成了多行。解决在写JOIN之前先用SELECT配合COUNT确认左右表的关联字段是否有重复值。如果业务上只需要保留一条记录常见做法是用关联子查询或者窗口函数在主查询前把右表去重。我一般会先跑一句SELECT dept_id, COUNT(*) FROM dept GROUP BY dept_id确认右表关联字段不重复再写JOIN这个习惯能避免很多莫名其妙的翻车。5.3 GROUP BY之后SELECT列不符合规范现象开启了ONLY_FULL_GROUP_BY模式的MySQL直接报错提示SELECT列不在GROUP BY子句中关闭了模式则查询能跑但结果里的非聚合列取值是随机的。原因GROUP BY之后每个分组只保留一行非分组字段如果不在聚合函数里就没有确定的取值。比如按部门分组后分组里有多名员工SELECT里的emp_name到底显示哪个人的名字数据库没有明确规则。解决要么把SELECT列放进GROUP BY要么用聚合函数包住要么改造成窗口函数。具体来说想取每个部门工资最高的员工姓名窗口函数比把emp_name加进GROUP BY更合适因为后者会让分组维度变得过细统计口径就变了。5.4 NOT IN遇到NULL就失控现象一条WHERE id NOT IN (SELECT dept_id FROM dept)查询返回结果为空但明显存在不符合条件的记录。原因子查询的结果集里如果包含NULLNOT IN的判断逻辑会变成“该值不等于任何值且不等于NULL”而单个值与NULL做比较的结果是UNKNOWNWHERE只保留TRUE的行UNKNOWN全部被过滤所以结果为空。解决在子查询里过滤掉NULL值WHERE id NOT IN (SELECT dept_id FROM dept WHERE dept_id IS NOT NULL)或者用NOT EXISTS替代。NOT EXISTS是逐行判断遇到NULL不会出现这种失控行为从可读性和稳定性上都优于NOT IN。这种问题平时不起眼线上查数据查到结果为空时很容易被误判为业务本身没数据实际上是被NULL坑了。5.5 UPDATE忘加WHERE把全表改了现象想更新一条员工薪资执行UPDATE emp SET salary 15000;之后发现全表所有人的薪资都变成了15000。原因UPDATE语句没有WHERE条件MySQL会按照全表范围执行更新。这种操作在开发环境里重启服务能恢复但在生产环境里就是事故级别的问题。解决执行UPDATE之前先写成同条件SELECT看到影响行数符合预期再改成UPDATE。MySQL客户端在执行不带WHERE的UPDATE时会弹出确认提示不要因为弹窗烦就顺手关了。PDF特别提醒养成在事务里执行UPDATE然后先ROLLBACK的习惯确认无误再COMMIT这是成本最低的后悔药。从那以后我每次执行数据变更SQL都会强制走一遍“先SELECT看影响范围再UPDATE接着检查结果最后COMMIT”的流程希望帮到你。6. 检验学习成果自己建一套练习库并跑通完整场景6.1 用10分钟建一个模拟业务库检验SQL水平最直接的方式不是做选择题而是给自己设计一个完整的小业务场景。我建议建一个简化版电商库包含用户表、订单表、订单明细表然后跑几个经典查询。这个场景覆盖了单表查询、多表JOIN、聚合统计、子查询、窗口函数等主要知识点一套练完基础技能基本就扎实了。CREATE TABLE users ( user_id INT PRIMARY KEY, user_name VARCHAR(50), register_date DATE ); CREATE TABLE orders ( order_id INT PRIMARY KEY, user_id INT, order_amount DECIMAL(10,2), order_date DATETIME, INDEX idx_user (user_id) ); CREATE TABLE order_items ( item_id INT PRIMARY KEY, order_id INT, product_name VARCHAR(100), quantity INT, price DECIMAL(10,2) );orders表的idx_user索引建立在user_id上就是为了让按用户查订单的JOIN查询能走索引而不是全表扫描。order_items表则模拟订单与商品的多行明细关系。自己插入几组测试数据用户和订单数量不用太多十几条就够验证逻辑。6.2 三个必做的小练习第一个练习是按用户统计总消费金额并只保留消费超过500元的用户这是GROUP BY加HAVING的标准组合SELECT u.user_name, SUM(o.order_amount) AS total_spent FROM users u JOIN orders o ON u.user_id o.user_id GROUP BY u.user_id, u.user_name HAVING total_spent 500 ORDER BY total_spent DESC;第二个练习是找每个用户最近的一笔订单用窗口函数ROW_NUMBER()按用户分组并按订单日期倒序编号取编号为1的记录SELECT user_id, order_id, order_date, amount FROM ( SELECT o.user_id, o.order_id, o.order_date, o.order_amount AS amount, ROW_NUMBER() OVER (PARTITION BY o.user_id ORDER BY o.order_date DESC) AS rn FROM orders o ) t WHERE rn 1;第三个练习是统计每件商品在所有订单中的销量排名用RANK()或DENSE_RANK()都行关键是区别这两个函数的排名逻辑RANK会在并列时跳过下一个名次DENSE_RANK不会跳过。业务上通常用DENSE_RANK因为连续的名次更好理解。6.3 进阶验证把PDF里的索引知识用起来练习库建好之后还可以验证一下索引的实际效果。在没有任何索引的order_items表上执行一条按商品名查询的语句然后用EXPLAIN看执行计划你会发现type是ALL扫描行数是全表行数。给product_name加上普通索引再查一次type会变成refrows大幅减少。这种前后对比的验证方式比只读PDF里的文字更有说服力。做完这些练习之后再回头看这份SQL基础教程PDF你会对每个章节的价值有更具体的感知。建表章节的约束设计、联结章节的行数差异、聚合章节的NULL陷阱、索引章节的性能优化、事务章节的隔离级别取舍每一条都对应着你亲手跑过的场景。从那以后我每次带新人入门SQL都建议他们按照“看一章PDF、跑一遍练习、再回看章节”的节奏来学这个循环走完SQL的地基才算真正打牢。希望帮到你。本文还有配套的精品资源点击获取

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号