AND 和 OR 的逻辑行为必须分清
AND 要求所有条件同时为真,OR 只要任一条件为真就成立。这不是“语法差异”,而是查询结果是否符合业务预期的根本分水岭。
比如:
SELECT * FROM users WHERE age > 18 AND city = 'Beijing'找的是“又成年、又在北京”的人;而
SELECT * FROM users WHERE age > 18 OR city = 'Beijing'找的是“成年者”或“北京人”——哪怕是个 16 岁的北京学生也会被拉进来。
混合使用时括号不是可选项,是必选项
MySQL 中
AND优先级远高于
OR,不加括号等于把逻辑交给编译器猜,结果往往和你脑内想的不一样。
WHERE age > 18 OR city = 'Beijing' AND salary > 5000实际等价于
WHERE age > 18 OR (city = 'Beijing' AND salary > 5000),不是你想要的“(年龄>18 或 城市=北京)且薪资>5000” 正确写法应为:
WHERE (age > 18 OR city = 'Beijing') AND salary > 5000再比如查“年龄60,且状态为 active”,必须写成:
WHERE (age 60) AND status = 'active';漏括号就会变成
age 60 AND status = 'active'),完全跑偏
性能陷阱:OR 容易让索引失效
当
OR连接的多个条件涉及不同字段(如
d_id = 1001 OR sex = '男'),MySQL 很难高效利用索引,尤其在大表上可能触发全表扫描。这不是写法错误,而是引擎限制。 如果字段有独立索引但没联合索引,
OR基本无法走索引优化 替代方案之一是用
UNION拆开:
(SELECT * FROM employee WHERE d_id = 1001) UNION (SELECT * FROM employee WHERE sex = '男'),让每个子查询独立走索引 更优解是建覆盖型联合索引(如
(d_id, sex)),再配合
IN或重写逻辑,但前提是业务允许条件收敛
别忽略 NULL 和空字符串的干扰
用
AND或
OR连接含
IS NULL的判断时,容易误以为逻辑对称。实际上
NULL = 'value'返回
UNKNOWN,不是
FALSE,会直接影响
AND/OR结果。 比如:
WHERE status = 'active' OR level IS NULL—— 如果某行
status是
NULL,整个表达式不会因
status = 'active'不成立就跳过,但也不会直接判假,得看三值逻辑规则 稳妥做法是显式处理:
WHERE (status = 'active' OR status IS NULL) AND (level IS NULL OR level > 0)测试时务必用真实含 NULL 数据验证,别只靠“看起来应该对”
括号不是为了好看,是防止逻辑被优先级悄悄改写;OR 不是不能用,但每加一个都要问一句:这个条件能不能走索引?有没有 NULL 暗坑?
