括号缺失会导致WHERE条件执行顺序错误,如a=1 OR b=2 AND c=3实际等价于a=1 OR (b=2 AND c=3),而非(a=1 OR b=2) AND c=3,易致漏数据或误查已删除记录。

WHERE里混用AND和OR不加括号,结果一定错
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。这种错位在软删除、多字段搜索、状态筛选等场景下直接导致漏数据或误返回已删除记录。
软删除场景下deleted = 0必须作为顶层约束
当你要查“匹配关键词且未删除”的数据时,deleted = 0 不能只挂在某个 OR 分支后面。常见错误写法:
WHERE nomor_formulir LIKE '%mikha%' OR harga_pelita LIKE '%5%' AND deleted = 0
这等价于:
WHERE nomor_formulir LIKE '%mikha%' OR (harga_pelita LIKE '%5%' AND deleted = 0)
只要 nomor_formulir 匹配,不管 deleted 是 0 还是 1 都会返回。✅ 正确做法是把所有搜索条件用括号包成一组,再整体与 deleted = 0 连接:
WHERE (nomor_formulir LIKE '%mikha%' OR harga_pelita LIKE '%5%') AND deleted = 0
- 如果
deleted字段在右表(如LEFT JOIN的table_formulir_pelita),记得写成table_formulir_pelita.deleted = 0,否则可能被优化器忽略或退化为INNER JOIN - 若搜索字段可能为
NULL,用COALESCE(nomor_formulir, '') LIKE '%mikha%'避免匹配失败
多个OR同字段时,优先用IN代替
像 status = 'active' OR status = 'pending' OR status = 'draft' 这类写法,不仅冗长,还容易因类型隐式转换(比如 '1' vs 1)引发全表扫描。✅ 改用 IN 更安全高效:
WHERE status IN ('active', 'pending', 'draft')-
IN列表长度不宜超过几百项,否则某些数据库(如 MySQL)会降级为全表扫描 -
IN无法替代跨字段逻辑,比如type = 'order' OR amount > 1000就不能简化 - 若列表来自参数,确保应用层做了长度校验和类型统一,防止注入或类型不一致
嵌套三层以上括号时,该拆就拆
像 ((a AND b) OR (c AND (d OR e))) 这种结构,人眼已经难校验,后续维护者也不敢轻易改。更可靠的做法是:
- 用
CTE提前定义子逻辑,比如WITH active_orders AS (SELECT * FROM t WHERE status = 'active') - 或拆成
UNION ALL:两个独立查询分别走索引,比一个带OR的大查询更容易命中索引、也更易调试 - 测试时务必插入含
NULL的数据行——column = 'X' OR column = 'Y'永远不匹配NULL,要补OR column IS NULL才完整
括号不是可选格式装饰,是你和数据库之间关于“哪部分先算”的书面契约。漏一个,结果就偏;嵌套太深,下次你自己都得重读三遍才敢动。

















