括号是AND/OR混合逻辑的刚需,因AND优先级恒高于OR;IN可安全高效替代同字段多OR;NULL需显式判断;OR易致索引失效,宜用UNION ALL拆分。

不加括号的 AND 和 OR 混合写法,几乎必然出错——数据库按固定优先级执行,人脑却按业务直觉读,两者对不上。
AND 优先级永远高于 OR,括号不是风格问题,是逻辑刚需
SQL 规范里 AND 的结合力天生强于 OR,等价于数学里的乘法 vs 加法。写 WHERE a = 1 OR b = 2 AND c = 3,实际执行的是 WHERE a = 1 OR (b = 2 AND c = 3),而非你脑中想的 WHERE (a = 1 OR b = 2) AND c = 3。
哪怕只混用一次,也必须显式加括号:
- 查“华东区已发货”或“所有已签收”订单:
WHERE (region = '华东' AND status = '已发货') OR status = '已签收' - 查“VIP客户且消费超5000”,或“非VIP但复购≥3次”:
WHERE (is_vip = 1 AND amount > 5000) OR (is_vip = 0 AND repeat_count >= 3) - 别信缩进或换行——执行器只认括号,格式纯属给人看的
IN 替代单字段多个 OR,更安全也更高效
当多个 OR 都在判断同一字段的等值(比如 status = 'A' OR status = 'B' OR status = 'C'),直接换成 IN:
- 语义清晰:
status IN ('A', 'B', 'C')比一长串OR更易读 - 优化器友好:多数数据库对
IN列表有专门优化,比等价OR更可能走索引 - 避免引号/类型陷阱:写
IN (1, 2, 3)不会因漏引号导致隐式转换;而id = 1 OR id = '2'可能触发全表扫描 - 注意边界:
IN不能替代跨字段逻辑,比如type = 'order' OR amount > 1000就没法用IN简化
NULL 值会让 AND/OR 行为“静默失效”
column = 'X' 永远不匹配 NULL 行,column != 'X' 也不匹配——NULL 参与任何比较都返回 UNKNOWN,而 WHERE 只接受 TRUE。
- 想包含空值?显式补判断:
WHERE (status = 'active' OR status IS NULL) - 用
COALESCE或CASE统一处理:WHERE COALESCE(status, 'unknown') IN ('active', 'unknown') - 别依赖
NOT IN查缺失值:若子查询含NULL,整条NOT IN返回空结果集——这是线上事故高发点 - 测试时务必插一条
status IS NULL的记录,看它是否被意外过滤
性能陷阱:OR 容易让索引“形同虚设”
OR 条件常导致优化器放弃使用索引,尤其当分支字段不同、或带函数时:
- 两个字段无联合索引?
WHERE a = 1 OR b = 2很可能全表扫描 - 改用
UNION ALL拆开:(SELECT * FROM t WHERE a = 1) UNION ALL (SELECT * FROM t WHERE b = 2 AND a != 1),可分别走索引 - 函数破坏索引:
UPPER(name) = 'MARY' OR age + 1 > 30基本无法命中索引,应提前计算或建函数索引 - 高区分度条件前置没用:WHERE 执行顺序由优化器决定,但把
id = 123这类主键等值放前面,能帮人快速理解主过滤逻辑
最危险的不是不会写括号,而是写了括号却没验证括号是否真按你设想的分组——上线前用几条构造数据跑一遍,比看一百遍文档都管用。










