SQL中AND优先级高于OR,混用时不加括号会导致逻辑错误;NOT优先级最高,需用括号明确作用范围;外连接中ON与WHERE的括号位置决定关联逻辑和过滤时机。

不加括号的 AND/OR 混用,90% 以上概率查出错数据——不是数据库错了,是你写的逻辑被优先级悄悄改写了。
AND 和 OR 的默认优先级到底怎么算
SQL 不按你换行或空格的位置分组,它严格遵循:NOT > AND > OR。写 WHERE a = 1 OR b = 2 AND c = 3,数据库实际执行的是 WHERE a = 1 OR (b = 2 AND c = 3),而不是你盯着屏幕想的 (a = 1 OR b = 2) AND c = 3。这个差异在 WHERE 后接多个条件时会直接导致漏数据或误召回。
常见错误现象:
- 本想查「状态是 active 且类型是 user 或 admin」,却写成
status = 'active' AND type = 'user' OR type = 'admin',结果所有type = 'admin'的记录全被拉出来,不管status是什么 - 外连接后加了
WHERE right_table.id IS NOT NULL,以为只是过滤右表非空,实际把左表没匹配上的行也剔除了,等效于内连接
什么时候必须加括号,什么时候可以不加
只要条件里同时出现 AND 和 OR,哪怕只有两个词,也建议显式加括号。这不是“以防万一”,而是让 SQL 和你的业务语义对齐。
实操建议:
- 每组独立业务含义的条件,必须用小括号包裹,例如查「北京的男用户」或「上海的 VIP 用户」,必须写成
(city = '北京' AND gender = '男') OR (city = '上海' AND is_vip = true) - 嵌套三层以上(比如
(a AND b) OR (c AND (d OR e))),人眼已难验证,应拆成 CTE 或子查询,别硬堆括号 - 用格式化工具(如 pgFormatter、SQLFluff)或手动缩进对齐括号,避免“括号迷宫”——你今天能看懂,下周自己都未必敢动
NOT 和括号搭配的典型翻车点
NOT 的作用范围常被低估。写 WHERE NOT a = 1 OR b = 2,实际是 WHERE (NOT a = 1) OR b = 2,几乎肯定不是你想要的。要表达「既不满足 a=1,也不满足 b=2」,得写 WHERE NOT (a = 1 OR b = 2);要表达「a≠1 且 b=2」,得写 WHERE (NOT a = 1) AND b = 2。
容易踩的坑:
- 用
NOT IN时,若子查询结果含NULL,整个条件恒为UNKNOWN,查不到任何数据——此时应改用NOT EXISTS或先排除NULL -
WHERE col NOT LIKE '%abc'看似合理,但前导通配符无法走索引;真要模糊查后缀,得接受性能代价,或改用全文检索 -
IN不处理NULL:col IN ('a', 'b')不会匹配col IS NULL,需单独加OR col IS NULL
ON 和 WHERE 中括号使用的分工差异
外连接场景下,ON 和 WHERE 对括号的敏感度完全不同:ON 里的条件决定“怎么连”,WHERE 里的条件决定“连完再筛谁”。一个括号放错位置,可能让 LEFT JOIN 变相失效。
使用场景举例:
- 想查所有用户 + 其订单数(含 0),右表过滤必须放
ON:LEFT JOIN orders o ON u.id = o.user_id AND o.status != 'cancelled'。如果写成WHERE o.status != 'cancelled',那些没订单的用户就没了 - 想查「有活跃订单的用户」,才该把状态判断放
WHERE,并确保o.id IS NOT NULL显式写出,避免 NULL 干扰 -
ON中的括号影响关联形状,WHERE中的括号影响最终结果集大小——两者不能互换,也不能省略逻辑分组
括号不是语法装饰,是把模糊的自然语言需求,锚定到确定的布尔代数结构上。写完每个 WHERE 子句,不妨默读一遍括号内的语义:“这一组,是不是一个不可再分的业务单元?” 如果答案是否定的,那括号还没加到位。










