where子句必须正确书写以准确过滤数据:字符串和日期须用单引号,null需用is null判断,多条件注意括号优先级;like慎用前置通配符,in列表不宜过长,between为闭区间且含时间时需手动设上限。

WHERE 子句的基本写法和常见错误
WHERE 不是可选的装饰,它是真正过滤数据的开关。漏写、错写条件或忽略 NULL 处理,查出来的结果往往和预期差很远。
最常犯的错是把字符串值不加引号:WHERE name = zhangsan 会报错或误判为列名/变量;正确写法是 WHERE name = 'zhangsan'。数字可以不加引号,但混用类型时(比如 id = '123' 查 INT 字段),MySQL 会隐式转换,可能触发全表扫描。
- 字符串、日期必须用单引号包裹,如
'2024-01-01' - 字段名、表名不要加单引号,否则变成字符串字面量
-
NULL不能用=判断,得用IS NULL或IS NOT NULL - 多个条件用
AND/OR连接,注意运算优先级,不确定就加括号
IN、BETWEEN 和 LIKE 的实际使用边界
这三个操作符看着简单,但性能和语义容易踩坑。比如 LIKE 以通配符开头('%abc')会导致索引失效;IN 列表过长(几百项)可能触发优化器放弃索引;BETWEEN 是闭区间,BETWEEN '2024-01-01' AND '2024-01-31' 会包含 1 月 31 日 00:00:00,但不包含 23:59:59 —— 如果字段含时间,得手动补上限。
-
IN (1, 2, 3)等价于多个=OR 组合,但比写三行OR更清晰 -
NOT IN遇到列表里有NULL,整条查询可能返回空结果(三值逻辑),建议改用NOT EXISTS -
BETWEEN a AND b要求a ,反着写不会报错但永远不匹配 -
LIKE 'abc%'可走索引,'%abc'或'%abc%'基本走不了
WHERE 中函数调用的性能代价
在 WHERE 条件里对字段用函数(比如 WHERE YEAR(create_time) = 2024),MySQL 无法使用 create_time 上的索引,只能全表扫描。这不是语法问题,而是执行计划层面的硬伤。
- 应改为范围写法:
WHERE create_time >= '2024-01-01' AND create_time -
LOWER(name) = 'alice'建议直接在字段上建函数索引(MySQL 8.0+ 支持),或统一存小写 -
STR_TO_DATE(str_date, '%Y-%m-%d')这类转换尽量移到应用层,别塞进 WHERE - 哪怕只是
WHERE id + 1 = 100,也会让id索引失效
WHERE 和 ORDER BY / LIMIT 的协作关系
很多人以为 WHERE 执行完才轮到 ORDER BY,其实优化器可能调整顺序,尤其当 ORDER BY 字段有索引而 WHERE 字段没有时。更关键的是:LIMIT 不会减少 WHERE 的计算量——它只截结果集,不跳过扫描。
- 如果
WHERE条件松散(比如只过滤掉 10% 数据),LIMIT 10仍可能扫几十万行才凑够 10 条 -
ORDER BY字段最好也在WHERE条件涉及的索引中,形成“覆盖索引”或“索引下推” - 分页深度大时(
LIMIT 10000, 20),考虑用游标方式(记录上一页最大 ID)替代OFFSET - EXPLAIN 结果里看
rows和Extra(比如出现Using filesort或Using temporary就要警惕)
WHERE 看似只是 SQL 里的一小段,但它直接决定 MySQL 是扫 10 行还是 1000 万行。真正难的不是写出来,而是判断它背后有没有走索引、会不会隐式转换、是否被函数拖垮——这些没法靠语法检查发现,得看 EXPLAIN 和实际执行时间。











