逻辑运算符
导学
实际业务中,筛选条件很少只有一个。"年龄大于 18 且部门是技术部"、"状态为 0 或 2 且未删除"——这类复合条件需要逻辑运算符来组合。
定义
逻辑运算符:用于组合多个条件表达式,返回 1(真)、0(假)或 NULL(未知)。MySQL 支持 AND、OR、NOT、XOR 四种逻辑运算。
真值表
| 条件1 | 条件2 | AND | OR | XOR |
|---|---|---|---|---|
| TRUE | TRUE | TRUE | TRUE | FALSE |
| TRUE | FALSE | FALSE | TRUE | TRUE |
| TRUE | NULL | NULL | TRUE | NULL |
| FALSE | FALSE | FALSE | FALSE | FALSE |
| FALSE | NULL | FALSE | NULL | NULL |
| NULL | NULL | NULL | NULL | NULL |
演示数据准备
DROP TABLE IF EXISTS employees;
CREATE TABLE employees (
emp_id INT PRIMARY KEY AUTO_INCREMENT,
emp_name VARCHAR(20),
dept VARCHAR(20),
score DECIMAL(5,2)
);
INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);
当前 employees 表中的完整数据如下:
| emp_id | emp_name | dept | score |
|---|---|---|---|
| 1 | 大翔 | 技术部 | 100 |
| 2 | 白歌 | 技术部 | NULL |
SQL 示例
场景一:AND 组合条件
当前数据状态:见上文 employees 表完整数据。
执行语句:
SELECT emp_name, dept, score FROM employees
WHERE dept = '技术部' AND score >= 90;
操作后结果:
| emp_name | dept | score |
|---|---|---|
| 大翔 | 技术部 | 100 |
结果解读:AND 要求两个条件同时为真。技术部且绩效大于等于 90 的员工只有大翔,因此只返回 1 条。如果加入第三个条件:
SELECT emp_name, dept, score FROM employees
WHERE dept = '技术部' AND score >= 90 AND emp_name = '大翔';
操作后结果:
| emp_name | dept | score |
|---|---|---|
| 大翔 | 技术部 | 100 |
结果解读:三个条件同时满足的只有大翔。白歌虽然属于技术部,但 score 为 NULL(不满足 >= 90),因此不返回。
场景二:OR 组合条件
当前数据状态:见上文 employees 表完整数据。
执行语句:
SELECT emp_name, dept, score FROM employees
WHERE dept = '产品部' OR score IS NULL;
操作后结果:
| emp_name | dept | score |
|---|---|---|
| 白歌 | 技术部 | NULL |
结果解读:满足任一条件即可。白歌的 score 为 NULL,因此 1 条被返回。当前表中没有产品部员工。
场景三:优先级陷阱(经典面试题)
当前数据状态:见上文 employees 表完整数据。
执行语句(错误写法):
-- 危险:本意是"技术部且绩效为 NULL,或者产品部且绩效为 NULL"
-- 实际执行:"(技术部且 NULL) 或 产品部"——语义错误
SELECT emp_name, dept, score FROM employees
WHERE dept = '技术部' AND score IS NULL OR dept = '产品部';
操作后结果:
| emp_name | dept | score |
|---|---|---|
| 白歌 | 技术部 | NULL |
结果解读:由于 AND 优先级高于 OR,实际执行的是 WHERE (dept = '技术部' AND score IS NULL) OR dept = '产品部'。当前表中没有产品部员工,因此只有白歌被返回。
正确写法(如果本意是"技术部或产品部中,绩效为 NULL 的人"):
SELECT emp_name, dept, score FROM employees
WHERE (dept = '技术部' OR dept = '产品部') AND score IS NULL;
操作后结果:
| emp_name | dept | score |
|---|---|---|
| 白歌 | 技术部 | NULL |
结果解读:加括号后先判断部门(技术部或产品部),再判断绩效是否为 NULL。当前表中没有产品部员工,因此只有白歌满足条件。
优先级规则:NOT > AND > OR。建议始终用括号显式分组,不要依赖默认优先级。
场景四:NOT 取反
当前数据状态:见上文 employees 表完整数据。
执行语句:
SELECT emp_name, dept FROM employees
WHERE NOT dept = '技术部';
-- 等价于
-- WHERE dept <> '技术部';
操作后结果:
| emp_name | dept |
|---|
结果解读:NOT 对条件取反,排除了技术部的大翔和白歌。当前表中没有产品部员工,因此返回空结果。NOT dept = '技术部' 等价于 dept <> '技术部'。
再看一个 NOT 与 IN 结合的例子:
SELECT emp_name, dept FROM employees WHERE dept NOT IN ('技术部');
操作后结果:
| emp_name | dept |
|---|
结果解读:NOT IN 排除列表中的值,返回部门不是技术部的员工。当前表中没有产品部员工,因此返回空结果。
场景五:IN 是 OR 的语法糖
当前数据状态:见上文 employees 表完整数据。
执行语句:
-- 以下两条完全等价
SELECT emp_name FROM employees WHERE dept = '技术部' OR dept = '产品部';
SELECT emp_name FROM employees WHERE dept IN ('技术部', '产品部');
操作后结果(两者相同):
| emp_name |
|---|
| 大翔 |
| 白歌 |
结果解读:IN 是多值 OR 的简洁写法。当选项很多时,IN 的可读性远好于一长串 OR。MySQL 5.7 优化器通常会将两者优化为相同的执行计划。
场景六:XOR(异或)
当前数据状态:见上文 employees 表完整数据。
执行语句:
SELECT emp_name, dept, score FROM employees
WHERE (score IS NULL) XOR (dept = '产品部');
操作后结果:
| emp_name | dept | score |
|---|---|---|
| 白歌 | 技术部 | NULL |
结果解读:XOR 要求两个条件有且仅有一个为真。让我们逐行分析:
- 大翔:
score IS NULL(假),dept = '产品部'(假)→ XOR 为假(未返回) - 白歌:
score IS NULL(真),dept = '产品部'(假)→ XOR 为真 ✓
大翔因两个条件都为假而被排除,白歌因恰好一个条件为真而被返回。
短路求值
MySQL 在求值逻辑表达式时采用短路求值(Short-circuit Evaluation):
AND:若左侧为 FALSE,右侧不再执行OR:若左侧为 TRUE,右侧不再执行
-- 如果 dept <> '技术部',右侧的复杂函数不会执行
WHERE dept = '技术部' AND LENGTH(phone) = 11;
这意味着应将筛选性强的条件放在左侧,可能减少不必要的计算。
常见误区
| 误区 | 正解 |
|---|---|
AND 和 OR 优先级相同 | AND 优先级高于 OR,混用必须加括号。 |
WHERE NOT col1 = 1 AND col2 = 2 | 解析为 WHERE (NOT col1 = 1) AND col2 = 2,而非 NOT (col1 = 1 AND col2 = 2)。 |
用 OR 连接索引列性能一定差 | MySQL 5.7 的索引合并(Index Merge)可以优化某些 OR 查询。 |
XOR 很常用 | 实际业务中极少使用,通常用 (a AND NOT b) OR (NOT a AND b) 替代。 |
面试考点
Q:AND 和 OR 的优先级?
NOT>AND>OR。建议始终用括号显式分组,增强可读性并避免歧义。
Q:下面这条 SQL 的查询条件是什么?
WHERE a = 1 OR b = 2 AND c = 3实际等价于WHERE a = 1 OR (b = 2 AND c = 3)。若要表达(a = 1 OR b = 2) AND c = 3,必须加括号。
Q:MySQL 的 XOR 在实际中常用吗?
极少使用。
XOR表达"二者有且仅有一个为真",这种业务场景不多。通常用(a AND NOT b) OR (NOT a AND b)替代,可读性更好。
Q:短路求值对性能有什么影响?
应将筛选性强的条件放在
AND的左侧或OR的左侧。AND左侧为假时右侧不执行;OR左侧为真时右侧不执行。这可以减少函数调用和复杂计算。
小结
AND要求所有条件为真,OR要求至少一个为真- 优先级:
NOT>AND>OR,混用时务必加括号 IN是多值OR的简洁写法- 短路求值意味着条件顺序可能影响性能
XOR在实际业务中极少使用
下一章引子:条件判断中除了比较和逻辑,还经常需要对数据进行计算——算术运算符让查询中的数学运算成为可能。