and优先级永远高于or,sql解析where时严格按not > and > or执行,不加括号会导致逻辑偏差,如where a=1 or b=2 and c=3实际等价于a=1 or (b=2 and c=3),必须显式加括号确保逻辑正确。

AND优先级永远高于OR,数据库不按你读的顺序执行
SQL解析WHERE时,根本不管换行、缩进或空格——它只认运算符优先级: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。这种错位在MySQL、PostgreSQL、SQL Server里完全一致,没法绕开。
不加括号的混用,90%以上概率查出错数据
常见错误现象包括:漏掉本该排除的记录、意外拉入不该出现的数据、线上报表突然多出/少掉一批用户。比如WHERE status = 'active' OR status = 'pending' AND amount > 1000,结果会把所有status = 'active'的记录全查出来,哪怕amount是NULL或0。这不是语法报错,而是静默逻辑偏差,查不到问题,只看到结果不对。
- 业务逻辑天然分组(如“北京男用户”或“上海VIP用户”)→ 必须写成
(city = '北京' AND gender = '男') OR (city = '上海' AND is_vip = true) - 混入
NOT时更危险:NOT status = 'draft' OR role = 'admin'等价于(NOT status = 'draft') OR role = 'admin',而非你想否定整个OR组合 - 工具不会提醒你少括号:
EXPLAIN只优化执行路径,sqlfluff规则L017才专门报这个坑
括号不是风格选择,是逻辑对齐的底线
哪怕只有一处AND和一处OR出现在同一层WHERE里,也必须显式加括号。人脑记不住嵌套层级,尤其当条件里混入IN、BETWEEN、函数调用或子查询时,优先级规则迅速失效。格式化工具(如sqlformat.org)会自动把A OR B AND C转成A OR (B AND C),这恰恰暴露了你原本写法的歧义。
- 把每个业务单元单独括起来,例如
(status = 'active')、(role = 'admin' AND level > 5),再用OR连接 - 避免裸链式结构:
A OR B AND C OR D——看着简单,但可维护性归零,后续加条件极易翻车 - 三层以上嵌套(如
((a AND b) OR (c AND (d OR e))))建议拆成CTE或子查询,别靠括号硬扛
ORM和生成SQL特别容易埋雷
很多ORM(如Django ORM、Sequelize)链式调用时,若没用闭包或显式分组,会悄悄产出没括号的混用语句。比如.where({ status: 'active' }).orWhere({ role: 'admin' }).andWhere({ level: { gt: 5 } }),生成的SQL很可能就是status = 'active' OR role = 'admin' AND level > 5。检查日志里的真实SQL,重点盯括号位置;复杂逻辑宁可用原始SQL或CTE,别信ORM“智能拼接”。
真正难的不是记住优先级,是在写完WHERE之后,下意识停半秒,问自己:“这个括号,是不是我脑子想的那个意思?”——多数线上bug,都死在这半秒的省略上。











