首页 / MySQL 入门教程 / WHERE 条件与运算符

MySQL 入门教程

WHERE 条件与运算符

本教程共 46 篇 · 第 20 篇 · 更新于 2026-07-30 · 约 11 分钟阅读

MySQLMySQL 入门教程WHERE运算符ANDORINBETWEENIS NULL

20. WHERE 条件与运算符

本节目标:学会用 WHERE 子句给查询加过滤条件,掌握比较运算符、逻辑运算符(AND/OR/NOT)、范围与集合运算符(IN/BETWEEN)、NULL 判断(IS NULL),以及运算符优先级和 NULL 参与运算的坑。

20.1 WHERE 的作用

上一章学的 SELECT * FROM users 把所有行都查出来了。但实际工作中,你通常只要其中一部分数据—比如”年龄大于 25 的用户”、“状态为 paid 的订单”。

WHERE 就是干这个的,它跟在 FROM 后面,用来过滤行:

SELECT username, age
FROM users
WHERE age > 25;

只有 age 大于 25 的行才会出现在结果里。WHERE 条件不满足的行,直接被过滤掉。

20.2 比较运算符

最常用的条件就是比较大小。MySQL 支持的比较运算符:

运算符含义示例
=等于WHERE age = 25
!=<>不等于WHERE age != 25
>大于WHERE age > 25
>=大于等于WHERE age >= 25
<小于WHERE age < 25
<=小于等于WHERE age <= 25

注意 SQL 里判断相等用单个 =,不是 ==。这是跟编程语言不一样的地方,新手容易写错。

-- 查状态为 paid 的订单
SELECT * FROM orders WHERE status = 'paid';

-- 查年龄不等于 25 的用户
SELECT * FROM users WHERE age <> 25;

-- 查金额大于 100 的订单
SELECT * FROM orders WHERE amount > 100;
Note

字符串也可以比较大小,按字典序。'a' < 'b''apple' < 'banana'。但实际开发中很少直接比较字符串大小,更多用 LIKE 模糊匹配(下一章讲)。

20.3 逻辑运算符:AND / OR / NOT

单个条件不够用时,用逻辑运算符组合多个条件。

AND:并且

AND 要求所有条件都满足:

-- 年龄大于 25 且状态为 paid 的订单
SELECT * FROM orders
WHERE amount > 100 AND status = 'paid';

两个条件都得满足,行才会被选中。

OR:或者

OR 只要满足一个条件就行:

-- 状态为 paid 或 refunded 的订单
SELECT * FROM orders
WHERE status = 'paid' OR status = 'refunded';

NOT:取反

NOT 对条件取反:

-- 状态不是 paid 的订单
SELECT * FROM orders
WHERE NOT status = 'paid';

-- 等价于
SELECT * FROM orders
WHERE status != 'paid';

优先级问题

AND 的优先级比 OR 高。这意味着:

WHERE age > 25 AND username = '张三' OR username = '李四'

实际执行的是:

WHERE (age > 25 AND username = '张三') OR username = '李四'

先算 AND,再算 OR。如果你想要的是”年龄大于 25,并且用户名是张三或李四”,得加括号:

WHERE age > 25 AND (username = '张三' OR username = '李四')
Warning

混用 AND 和 OR 时,一定要加括号。别依赖默认优先级,哪怕你背得出来,你的同事不一定知道。加括号既是给数据库看的,也是给人看的。我之前排查过一个 bug,就是少了一对括号导致条件逻辑完全变了。

20.4 IN:在指定集合中

IN 用来判断一个值是否在一组值里面,比写一堆 OR 简洁得多:

-- 查状态为 paid、shipped 或 refunded 的订单
SELECT * FROM orders
WHERE status IN ('paid', 'shipped', 'refunded');

等价于:

SELECT * FROM orders
WHERE status = 'paid' OR status = 'shipped' OR status = 'refunded';

显然 IN 写法更短更清晰。

NOT IN 取反,查不在集合里的:

SELECT * FROM orders
WHERE status NOT IN ('paid', 'shipped', 'refunded');
Note

IN 后面的列表里如果有 NULL,结果可能出乎意料。NOT IN 碰到 NULL 会导致整个查询返回空结果。这个坑后面讲 NULL 时详细说。

IN 还能跟子查询配合:

-- 查有订单的用户
SELECT * FROM users
WHERE id IN (SELECT user_id FROM orders);

子查询章节会详细讲这个用法。

20.5 BETWEEN:范围查询

BETWEEN 用来查某个范围内的值,包含边界:

-- 查年龄在 20 到 30 之间的用户(包含 20 和 30)
SELECT * FROM users
WHERE age BETWEEN 20 AND 30;

等价于:

SELECT * FROM users
WHERE age >= 20 AND age <= 30;

NOT BETWEEN 查范围外的:

SELECT * FROM users
WHERE age NOT BETWEEN 20 AND 30;

BETWEEN 对日期也特别好用:

-- 查 7 月份的订单
SELECT * FROM orders
WHERE created_at BETWEEN '2026-07-01 00:00:00' AND '2026-07-31 23:59:59';
Tip

BETWEEN闭区间,包含两个边界值。这是跟某些编程语言里的范围判断不一样的地方(有些是前闭后开)。记住了:BETWEEN 两头的值都算在内。

20.6 IS NULL:判断空值

NULL 在 MySQL 里是个特殊的存在,它表示”没有值”或”未知值”。判断 NULL 不能用 =

-- 错误写法:查不出任何结果
SELECT * FROM users WHERE email = NULL;

-- 正确写法
SELECT * FROM users WHERE email IS NULL;

判断非空用 IS NOT NULL

SELECT * FROM users WHERE email IS NOT NULL;
Warning

WHERE email = NULL 不会报错,但永远查不出结果。因为 NULL 跟任何值比较(包括另一个 NULL)结果都是 NULL,不是 true。这是 SQL 里最容易踩的坑之一。记住:判断 NULL 永远用 IS NULL / IS NOT NULL。

20.7 NULL 的特殊行为

NULL 在 MySQL 中有一套独特的规则,必须理解清楚:

NULL 参与运算

任何值跟 NULL 做运算,结果都是 NULL:

SELECT 100 + NULL;   -- 结果:NULL
SELECT NULL = NULL;  -- 结果:NULL(不是 1/true)

NULL 参与比较

NULL 跟任何值比较(=、>、<、!=),结果都是 NULL,不是 false:

SELECT * FROM users WHERE age > NULL;  -- 查不出任何行
SELECT * FROM users WHERE age != NULL; -- 也查不出任何行

NOT IN 的 NULL 陷阱

-- 如果 orders 表里有 user_id 为 NULL 的行
SELECT * FROM users
WHERE id NOT IN (SELECT user_id FROM orders);

子查询结果里只要有一个 NULL,整个 NOT IN 就返回空。因为 id NOT IN (1, 2, NULL) 相当于 id != 1 AND id != 2 AND id != NULL,而 id != NULL 永远是 NULL,整个条件就废了。

Tip

NOT IN 配合子查询时,在子查询里加 WHERE 列 IS NOT NULL 过滤掉 NULL,能避免这个坑。或者干脆改用 NOT EXISTS,后面章节会讲。

用 IFNULL 和 COALESCE 处理 NULL

如果某列可能有 NULL,查询时想给个默认值,用 IFNULLCOALESCE

-- age 为 NULL 时显示 0
SELECT username, IFNULL(age, 0) AS age FROM users;

-- COALESCE 返回第一个非 NULL 的值
SELECT username, COALESCE(age, 0) AS age FROM users;

COALESCE 可以接受多个参数,返回第一个非 NULL 的:

SELECT COALESCE(NULL, NULL, email, '无邮箱') FROM users;

20.8 运算符优先级

当一条 WHERE 里有多种运算符时,MySQL 按优先级从高到低执行。常见的优先级:

优先级运算符
!(NOT)
比较运算符(=, >, <, >=, <=, !=, IS, IN, BETWEEN, LIKE)
&&(AND)
||(OR)

实际使用中,NOT 优先级最高,比较运算符次之,AND 再次,OR 最低。

-- NOT 先执行,然后比较,然后 AND,最后 OR
WHERE NOT status = 'deleted' AND age > 20 OR amount > 500
-- 等价于
WHERE (NOT status = 'deleted') AND (age > 20) OR (amount > 500)
Note

别背优先级表,永远加括号。括号能让逻辑一目了然,也能避免优先级理解错误导致的 bug。这条建议适用于所有 SQL 编写场景。

20.9 WHERE 的限制

WHERE 里可以用的东西很灵活,但也有几个限制:

不能用列别名:因为 WHERE 在 SELECT 之前执行,别名还没生成。

-- 报错
SELECT amount * 0.9 AS 折后价 FROM orders WHERE 折后价 > 100;

-- 正确写法:在 WHERE 里重复表达式
SELECT amount * 0.9 AS 折后价 FROM orders WHERE amount * 0.9 > 100;

不能用聚合函数:聚合函数在 GROUP BY 阶段计算,WHERE 在分组之前执行。

-- 报错
SELECT status, COUNT(*) FROM orders WHERE COUNT(*) > 5 GROUP BY status;

-- 正确写法:用 HAVING(后面章节讲)
SELECT status, COUNT(*) FROM orders GROUP BY status HAVING COUNT(*) > 5;

20.10 小结

WHERE 是查询的灵魂,不会 WHERE 等于不会查询。核心记住几点:比较用 =<> 逻辑用 AND/OR/NOT、集合用 IN、范围用 BETWEEN、空值用 IS NULL。混用运算符时加括号,碰到 NULL 时格外小心。下一章学模糊查询,用 LIKE 和正则表达式匹配字符串模式。