简介:这份资源是B站Mosh老师SQL三小时入门课程的配套笔记,以PDF形式整理,面向零基础或希望系统梳理SQL核心语法的开发者与数据分析初学者。内容覆盖SQL基础知识、SELECT语句、WHERE子句,以及逻辑操作符、IN、BETWEEN、LIKE、REGEXP等常用操作符,并延伸至IS NULL、ORDER BY、LIMIT、各类JOIN与UNION等查询要点,帮助读者快速建立完整的SQL知识框架。资源包内共1个PDF文件,大小约2.43MB,轻量便携,适合随时查阅与复习。目前已有976人学习下载,说明其在入门学习者中具有一定认可度。笔记以速查表形式组织,条理清晰,便于对照语法示例理解条件筛选、模式匹配与多表连接等实际用法,适合作为课程学习后的巩固材料或日常开发中的快速参考手册。
1. SQL 三小时笔记的知识地图:从一条 SELECT 到多表 JOIN 的完整骨架
很多人学 SQL 的路径是反的:先背JOIN的四种类型,再回头补WHERE和ORDER BY,结果写查询时脑子里是一堆碎片。这份笔记的价值在于它给了一条清晰的骨架——从单表查询到多表关联,每一步只增加一个概念。整张地图大致分四层:第一层是基础语法(注释、分号、大小写),第二层是单表查询(SELECT、WHERE、逻辑运算符、IN、BETWEEN、LIKE、REGEXP、IS NULL),第三层是结果集加工(ORDER BY、LIMIT),第四层是多表操作(INNER JOIN、OUTER JOIN、USING、CROSS JOIN、UNION)和数据写入(INSERT)。适合已经能写简单查询、但知识点散落一地的人拿来重新串一遍。下面按这条骨架逐层拆开,把每个子句的语法、参数含义和容易翻车的地方都过一遍。
2. 单表查询的六个过滤工具:WHERE、逻辑运算符与模式匹配
2.1 WHERE 子句与比较运算符:过滤的起点
WHERE是所有过滤逻辑的入口,它跟在FROM后面,对每一行做条件判断,只保留条件为真的行。比较运算符一共六个:>、>=、<、<=、=、<>(或!=)。这里最容易忽略的是<>和!=在 MySQL 里完全等价,但有些数据库只认其中一种,写笔记时最好两个都记上。
-- 筛选积分大于 1000 的客户 SELECT * FROM customers WHERE points > 1000;参数说明:points是列名,1000是阈值,>表示严格大于。如果要包含等于,必须写成>=,这是最常见的边界错误——很多人写BETWEEN 100 AND 200时以为不包含端点,实际上 MySQL 的BETWEEN是闭区间,两端都包含。
2.2 逻辑运算符 AND、OR、NOT:组合条件的优先级陷阱
AND要求两边都为真,OR只要一边为真,NOT对条件取反。单独用都不难,难的是混用时的优先级:AND的优先级高于OR,所以A OR B AND C会被解释成A OR (B AND C),而不是(A OR B) AND C。血泪经验是:只要同时出现AND和OR,一律加括号,别赌自己的记忆。
-- 出生日期在 1990 年之后,或者积分大于 1000 SELECT * FROM customers WHERE birthdate > '1990-01-01' OR points > 1000; -- 用 NOT 取反:出生日期不在 1990 年之后 SELECT * FROM customers WHERE NOT (birthdate > '1990-01-01');NOT后面跟括号是安全写法,如果写成NOT birthdate > '1990-01-01',虽然也能跑,但可读性差,复习时容易看错逻辑。
2.3 IN 与 BETWEEN:列表匹配和区间匹配
IN用来判断某个值是否在一个离散列表里,BETWEEN判断是否在连续区间内。两者都能用OR改写,但IN和BETWEEN更短、更不容易写错。
-- 客户来自 VA、NY、CA 三个州 SELECT * FROM customers WHERE state IN ('VA', 'NY', 'CA'); -- 积分在 100 到 200 之间(包含两端) SELECT * FROM customers WHERE points BETWEEN 100 AND 200;重点:IN的列表里可以放数字、字符串、日期,但类型要一致;BETWEEN对小值在前、大值在后有要求,写反了会返回空结果,而且不报错——这是最隐蔽的翻车点之一。
2.4 LIKE 与 REGEXP:两种模式匹配的分工
LIKE只支持两个通配符:%匹配任意数量字符,_匹配恰好一个字符。REGEXP支持正则表达式,能力更强,但写法也更复杂。
-- 名字以 b 开头 SELECT * FROM customers WHERE first_name LIKE 'b%'; -- 名字以 a 开头(正则写法) SELECT * FROM customers WHERE first_name REGEXP '^a'; -- 名字以 ey 或 on 结尾 SELECT * FROM customers WHERE first_name REGEXP 'ey$|on$'; -- 名字包含 b 后面跟着 r 或 u SELECT * FROM customers WHERE first_name REGEXP 'b[ru]';正则元字符速查:^表示字符串开头,$表示结尾,|表示或,[abc]匹配其中任意一个字符,[a-d]匹配 a 到 d 范围内的任意字符。梳理下来会发现,LIKE能做的事REGEXP都能做,但LIKE在简单前缀匹配时性能更好,日常查询优先用LIKE,复杂模式再上REGEXP。
2.5 IS NULL:空值的专用判断
NULL在 SQL 里不是 0,也不是空字符串,它代表“未知”。任何值与NULL做比较运算(包括= NULL)结果都不是真,所以必须用IS NULL或IS NOT NULL。
-- 找出没有电话号码的客户 SELECT * FROM customers WHERE phone IS NULL;易错点:WHERE phone = NULL不会报错,但永远返回空结果。这个坑几乎每个人都会踩一次,记住“空值只能用 IS 判断”就能避开。
3. 结果集加工与多表关联:ORDER BY、LIMIT 和四种 JOIN
3.1 ORDER BY 与 LIMIT:排序和截断的执行顺序
ORDER BY按指定列排序,默认升序(ASC),可以显式写DESC降序。多列排序时,先按第一列排,第一列相同的再按第二列排。LIMIT用来限制返回行数,LIMIT 6, 3表示跳过前 6 行,返回接下来的 3 行——注意第一个数字是偏移量,不是起始行号。
-- 先按州升序,再按名字降序 SELECT * FROM customers ORDER BY state, first_name DESC; -- 只返回 3 条 SELECT * FROM customers LIMIT 3; -- 跳过 6 条,返回 3 条 SELECT * FROM customers LIMIT 6, 3;重点:ORDER BY在WHERE之后执行,LIMIT在ORDER BY之后执行。如果先LIMIT再排序,结果就是错的。另外,LIMIT的偏移量写法在数据量大时性能会下降,复习时知道这个背景即可。
3.2 INNER JOIN 与 OUTER JOIN:匹配与不匹配的分界
INNER JOIN只返回两张表中匹配的行,LEFT JOIN返回左表全部行,右表没有匹配的用NULL填充。RIGHT JOIN反过来,但实际写查询时几乎都用LEFT JOIN,因为可以调整表顺序达到同样效果。
-- 内连接:只返回有订单的客户 SELECT * FROM customers c JOIN orders o ON c.customer_id = o.customer_id; -- 左连接:返回所有客户,包括没有订单的 SELECT * FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id;参数说明:c和o是表别名,ON后面是连接条件。梳理下来会发现,JOIN默认就是INNER JOIN,写不写INNER都一样。LEFT JOIN的结果里,右表列出现NULL就说明该行在右表没有匹配——这是排查“哪些客户没下过单”的标准手法。
3.3 USING、CROSS JOIN 与 UNION:简化写法和集合合并
当两张表的连接列名完全相同时,可以用USING替代ON,写法更短。CROSS JOIN返回笛卡尔积,把左表每一行和右表每一行组合,实际业务里用得少,但理解它有助于明白JOIN的本质。UNION把两个查询结果上下拼在一起,要求列数和类型一致。
-- USING 简化连接 SELECT * FROM customers c JOIN orders o USING (customer_id); -- 交叉连接:每种颜色配每种尺寸 SELECT * FROM colors CROSS JOIN sizes; -- 合并客户和潜在客户的名字与地址 SELECT name, address FROM customers UNION SELECT name, address FROM clients;注意:UNION会自动去重,如果不想去重就用UNION ALL。CROSS JOIN的结果行数是两张表行数的乘积,小表测试时没问题,大表上跑就是灾难,复习时记住这个数量级关系。
3.4 INSERT INTO:写入数据的两种形式
INSERT INTO用来向表中添加行,可以一次插一条,也可以一次插多条。列名列表和值列表要一一对应,不想赋值的列可以用DEFAULT让数据库填默认值。
-- 插入单条记录 INSERT INTO customers(first_name, phone, points) VALUES ('Mosh', NULL, DEFAULT); -- 插入多条记录 INSERT INTO customers(first_name, phone, points) VALUES ('Mosh', NULL, DEFAULT), ('Bob', '1234', 10);重点:NULL是显式写入空值,DEFAULT是让数据库用该列的默认值,两者含义不同。如果列有NOT NULL约束且没有默认值,插入时省略该列会报错。
4. 易漏点与易错点:五个复习时最容易翻车的地方
4.1 易漏点一:BETWEEN 的边界包含关系
为什么漏:很多教程只说“在什么范围内”,不强调是否包含端点,导致写查询时凭感觉。怎么补:记住 MySQL 的BETWEEN是闭区间,BETWEEN 100 AND 200包含 100 和 200。如果要不包含端点,必须用> 100 AND < 200。
4.2 易漏点二:NULL 的比较运算永远不为真
为什么漏:NULL在直觉上像“空”,容易当成一个普通值去比较。怎么补:所有涉及NULL的判断一律用IS NULL或IS NOT NULL,写完查询后专门检查一遍有没有= NULL的写法。
4.3 易漏点三:AND 和 OR 混用时的优先级
为什么漏:AND优先级高于OR这件事在简单例子里看不出来,一旦条件变多就出错。怎么补:只要同时出现AND和OR,无条件加括号,把逻辑分组写清楚,别依赖默认优先级。
4.4 易漏点四:LEFT JOIN 后 WHERE 过滤右表列会退化成 INNER JOIN
为什么漏:LEFT JOIN的本意是保留左表全部行,但如果在WHERE里对右表列加条件(比如WHERE o.status = 'shipped'),右表为NULL的行会被过滤掉,结果和内连接一样。怎么补:如果确实要保留左表全部行,右表的过滤条件应该写在ON后面,而不是WHERE里。
4.5 易漏点五:LIMIT 偏移量的含义
为什么漏:LIMIT 6, 3看起来像“从第 6 行开始取 3 行”,实际是“跳过 6 行,取 3 行”,起始行是第 7 行。怎么补:把LIMIT offset, count读成“跳过 offset 条,返回 count 条”,写分页查询时用(页码 - 1) * 每页条数算偏移量。
5. 复习清单:三小时笔记的查漏补缺路线
复习这份笔记,最有效的方式不是从头再读一遍,而是按“写查询的顺序”反向检查。下面这张清单按实际写 SQL 时的决策顺序排列,每一条都对应一个可以立刻验证的动作。
| 检查项 | 验证方式 | 对应知识点 |
|---|---|---|
| 表名和列名是否写对 | 先SELECT *跑一次 | FROM / SELECT |
| 过滤条件是否覆盖边界 | 手动代入端点值测试 | WHERE / BETWEEN |
| 空值判断是否用 IS | 搜索查询里有没有= NULL | IS NULL |
| AND/OR 是否加括号 | 把条件单独跑一遍对比结果 | 逻辑运算符 |
| 模式匹配是否用对通配符 | %和_分别测试 | LIKE / REGEXP |
| 排序和截断顺序是否正确 | 先去掉 LIMIT 看全量排序 | ORDER BY / LIMIT |
| JOIN 类型是否匹配需求 | 左表行数是否全部保留 | INNER / LEFT JOIN |
| 右表过滤是否写在 ON 里 | 检查 WHERE 里有没有右表列 | LEFT JOIN 退化 |
| UNION 是否需要去重 | 对比 UNION 和 UNION ALL 行数 | UNION |
| INSERT 列和值是否一一对应 | 数一遍列名和值的个数 | INSERT INTO |
这份清单可以打印出来贴在显示器旁边,每次写完查询逐条过一遍。我自己的习惯是:只要查询里同时出现JOIN和WHERE,就强制走一遍第 7 和第 8 项,因为这两个地方翻车最多,而且不报错,只是结果悄悄变少。从那以后我每次写多表查询都先把LEFT JOIN的左表行数单独查一遍,再对比最终结果行数,不一致就回头查WHERE条件。希望这份梳理帮到你。
本文还有配套的精品资源,点击获取