多个查询条件必须用and或or显式连接;and条件全真才匹配,or需注意优先级并加括号;in替代多or更安全;or易致索引失效,可用union all拆分。

多个查询条件必须用 AND 或 OR 显式连接,不能省略逻辑运算符,也不能靠空格或换行隐含关系。
WHERE 后面怎么写多个 AND 条件?
所有条件都必须为真才匹配,直接用 AND 串起来就行。常见错误是漏写 AND 或误用逗号分隔 —— SQL 不认逗号作为逻辑连接符。
- 正确:
WHERE status = 'active' AND age > 18 AND is_deleted = 0 - 错误:
WHERE status = 'active', age > 18(语法报错) - 错误:
WHERE status = 'active' age > 18(语法报错) - 注意字段类型:比如
age > '18'在某些引擎里会触发隐式转换,建议保持类型一致
混合使用 AND 和 OR 时为什么总查出意外数据?
因为 AND 优先级高于 OR,不加括号就等同于给 AND 部分自动加了括号。你以为在查“A 或 B 且 C”,实际执行的是“A 或 (B 且 C)”。
- 危险写法:
WHERE type = 'user' OR role = 'admin' AND created_at > '2024-01-01' - 等价于:
WHERE type = 'user' OR (role = 'admin' AND created_at > '2024-01-01') - 想要“(type=user 或 role=admin)且 created_at 新”,必须写:
WHERE (type = 'user' OR role = 'admin') AND created_at > '2024-01-01' - 哪怕只有一处不确定,也建议统一加括号,避免靠记忆优先级
同一字段多个等值条件,别硬写一堆 OR
比如 status = 'draft' OR status = 'pending' OR status = 'active',既啰嗦又容易漏条件,还可能影响索引选择。
- 换成
status IN ('draft', 'pending', 'active')更安全、更易读、优化器也更友好 -
IN不能处理NULL:status IN ('a', NULL)不会匹配status IS NULL的行,得单独补上OR status IS NULL - 子查询用
IN要小心:MySQL 8.0+、PostgreSQL 支持较好;SQLite 对大结果集的IN (SELECT ...)可能卡顿甚至 OOM
OR 导致查询变慢,不是加了索引就万事大吉
很多表明明有索引,OR 一出现就全表扫描 —— 这不是 bug,是多数旧版优化器的默认行为。
- 典型失效场景:
WHERE user_id = 123 OR order_date > '2024-01-01',即使两字段都有单列索引,MySQL 5.7 基本放弃索引合并 - MySQL 8.0+ 开启
optimizer_switch='index_merge=on'才可能走 index merge,但不稳定 - 更可控的替代方案是拆成
UNION ALL:(SELECT ... WHERE user_id = 123) UNION ALL (SELECT ... WHERE order_date > '2024-01-01' AND user_id != 123) - 注意:用
UNION会去重,开销更大;UNION ALL不去重,但需确保逻辑无交集,否则结果重复
真正麻烦的从来不是写对语法,而是判断哪些条件该合并在一个 WHERE 里,哪些该拆成多个查询再合并 —— 这得看数据分布、索引结构和执行计划,光背规则没用。










