多条件组合检索需规范书写以保障性能与安全:or与and混用必须加括号明确逻辑优先级;含or的复合条件须用括号包裹;避免在索引列上使用函数或计算,应将函数移至参数侧。

多条件组合检索写得不好,轻则慢几倍,重则直接拖垮数据库连接。关键不在“能不能查出来”,而在“查得有多稳、多快、多安全”。
WHERE子句里AND和OR混用必须加括号
不加括号时,AND 优先级永远高于 OR,哪怕你肉眼觉得“应该先算OR”。比如这句:
SELECT * FROM orders WHERE status = 'shipped' OR status = 'canceled' AND amount > 1000
实际执行逻辑是:(status = 'shipped') OR (status = 'canceled' AND amount > 1000),而不是你想要的“已发货或已取消,且金额都大于1000”。
- 所有含
OR的复合条件,只要不是最外层单逻辑,一律用括号包裹 - 即使只有两个条件,也建议显式写成
(status = 'shipped' OR status = 'canceled') AND amount > 1000 - MySQL 8.0+ 虽然会做部分常量折叠,但不会帮你重写逻辑顺序
避免在索引列上用函数或计算
哪怕只多套一层 YEAR(created_at) 或 UPPER(name),都会让该列上的索引失效,触发全表扫描。
- 把函数挪到参数侧:用
created_at >= '2025-01-01' AND created_at ,别用 <code>YEAR(created_at) = 2025 - 大小写比较统一存小写,查询时也用小写;或建函数索引(MySQL 8.0.13+ 支持
CREATE INDEX idx_name_lower ON users ((LOWER(name)))) - 日期范围尽量用左闭右开,避免
BETWEEN带来的边界歧义和隐式类型转换
用IN替代多个OR,但注意数量阈值
IN 在语义和性能上通常比等长的 OR 链更友好,但不是无上限的。
- MySQL 对
IN列表长度没有硬性限制,但超过 500 项后,预编译耗时明显上升,优化器可能放弃使用索引 - 如果动态条件可能超限(比如前端传来几百个ID),改用临时表或
EXISTS+ 子查询更稳妥 - 不要写
IN (NULL, 'a', 'b')——NULL在IN中永远不匹配,整条条件变恒假
参数化查询不是可选项,是唯一安全路径
任何用户可控的输入(搜索框、下拉筛选、URL参数)拼进 SQL,不走参数化,就是给 SQL 注入留门。
- Python 用
sqlite3时,必须用?占位符,而不是f"WHERE name = '{name}'" - Node.js 的
mysql2库中,用conn.execute('SELECT * FROM users WHERE id = ?', [id]),别用模板字符串 - ORM 如 Django ORM、SQLAlchemy 默认参数化,但手动写
.extra()或原生 SQL 时仍需自查
最容易被忽略的一点:前端传来的空字符串、空数组、undefined,后端没做校验就直接塞进参数列表,会导致查询语义错乱或报错 —— 这类“合法但无效”的输入,比恶意输入更常引发线上问题。











