括号不是可选而是执行逻辑的开关,SQL按NOT>AND>OR优先级执行,混用时必须显式加括号,否则语义被篡改导致结果错误。

不加括号的 AND 和 OR 混用,90% 以上概率查出错数据——不是数据库错了,是你写的逻辑被优先级悄悄改写了。
为什么括号不是“可选”,而是执行逻辑的开关
SQL 严格按 NOT > AND > OR 执行,不看你换行或空格。写 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。这两个结果集完全不重叠。
- 人脑读条件靠语义分组,数据库只认括号分组
- 哪怕只出现一次
AND和OR,也必须显式括起来 - 缩进、空行、注释对执行顺序零影响,纯属给人看的
哪些场景必须立刻加括号
只要业务上是“几组独立条件之间的或/且关系”,就必须用括号圈出每组完整语义。
- 查「北京的男用户」或「上海的 VIP 用户」→
WHERE (city = '北京' AND gender = '男') OR (city = '上海' AND is_vip = true) - 查「状态是 active 且类型是 user 或 admin」→ 错误写法:
status = 'active' AND type = 'user' OR type = 'admin';正确写法:WHERE status = 'active' AND (type = 'user' OR type = 'admin') - 外连接后要过滤右表非空但保留左表 →
LEFT JOIN ... ON ... WHERE (right_table.id IS NOT NULL)必须括起来,否则等效内连接
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,注意AND前的括号不能省 - 子查询中用
NOT IN?如果子查询返回NULL,整条语句结果为空——这不是 bug,是 SQL 标准行为,必须提前WHERE x IS NOT NULL过滤
嵌套三层以上就该拆,别硬堆括号
像 (a AND b) OR (c AND (d OR e)) 这种结构,人眼已难验证真假,后期维护极易引入错误。
- 超过两层嵌套时,优先考虑用 CTE 拆:先
WITH active_users AS (...),再SELECT ... FROM active_users WHERE ... - 或者用
UNION ALL拆分支,尤其当各分支能走不同索引时,性能反而更好 - 用
pgFormatter或SQLFluff自动格式化,让括号缩进对齐——今天你能看懂,下周自己都未必敢动
最常被忽略的不是语法,而是测试:插入一条 type = 'order' AND amount = 50 的记录,跑一遍你的 WHERE,看它是否意外被包含或排除——边界数据比语法检查更早暴露括号漏写。

















