
MySQL 中 AND、OR、NOT 的优先级和括号必要性
MySQL 默认按 NOT → AND → OR 顺序执行逻辑运算,不加括号极易出错。比如 WHERE status = 'active' OR role = 'admin' AND level > 5 实际等价于 WHERE status = 'active' OR (role = 'admin' AND level > 5),而非你想表达的「活跃用户或管理员」且「等级大于5」。
- 所有含混合运算的条件,只要语义不是严格左到右(且不符合默认优先级),必须用
()显式分组 -
NOT会作用于紧邻的整个表达式,NOT a = 1 AND b = 2等价于(NOT (a = 1)) AND (b = 2),不是NOT (a = 1 AND b = 2) - 用
EXPLAIN查看执行计划时,括号不影响索引使用,但写错逻辑会导致结果集错误——这比性能问题更难排查
用 AND 连接多字段条件时的 NULL 处理陷阱
AND 遇到 NULL 会返回 UNKNOWN,而 WHERE 只接受 TRUE,所以 col = 'x' AND col2 IS NULL 是安全的,但 col = 'x' AND col2 = NULL 永远不成立——因为 = NULL 永远是 UNKNOWN,不是 TRUE。
- 判断 NULL 必须用
IS NULL或IS NOT NULL,绝不用= NULL -
AND条件中任一子句为FALSE或UNKNOWN,整条就失效;想包含 NULL 场景,得显式写col IS NULL OR col = 'x' - 如果字段有大量 NULL,又用了
AND col != 'blocked',那些 NULL 行会被直接过滤掉,常被误认为“数据丢了”
用 OR 替代多个 IN 时的性能与可读性权衡
写 WHERE type = 'A' OR type = 'B' OR type = 'C' 和 WHERE type IN ('A','B','C') 逻辑等价,但 MySQL 优化器对 IN 的处理更成熟,尤其在有索引时能更好利用范围扫描。
- 超过 3 个离散值,优先用
IN;手写长串OR易漏改、难维护 -
OR连接不同字段(如name = 'a' OR email = 'b')大概率导致索引失效,此时应考虑UNION分拆查询 - 注意
OR条件中若混入函数(如UPPER(name) = 'A' OR age > 30),前半部分基本无法走索引
NOT 配合复杂表达式的常见翻车点
NOT 最容易让人直觉误判,比如 NOT (a > 10 AND b 等价于 <code>a = 5,而不是 a = 5。德·摩根定律在这里不是理论题,是每天写错的现实。
- 避免嵌套否定:不要写
NOT (status != 'done'),直接写status = 'done' -
NOT IN遇到子查询含NULL会整个返回空结果集——这是线上最隐蔽的 Bug 来源之一 - 想排除某类记录,优先用
!=或,只在必须否定整个组合条件时才用NOT (…)
逻辑运算本身很简单,但 MySQL 对 NULL 的三值逻辑、运算符优先级、以及索引能否生效这三件事叠加在一起,会让一个看似普通的 WHERE 条件变得极难推演。别信直觉,有疑问就用 SELECT … WHERE … 加几行测试数据当场验证。










