MySQL WHERE 条件支持标准 SQL 运算符,但部分行为受字段类型、字符集和 SQL 模式影响,不是所有运算符在所有场景下都等价或安全。
基本比较运算符(=、!=、、、>=)
这些是 WHERE 最常用的运算符,适用于数值、日期、字符串(按排序规则比较):
=是严格相等判断,对
NULL返回
UNKNOWN(不是
FALSE),所以
col = NULL永远不成立,必须用
col IS NULL
!=和 等价,但部分旧版客户端或 ORM 可能默认只识别其中一种 字符串比较是否区分大小写,取决于字段的 collation(如
utf8mb4_0900_as_cs区分,
utf8mb4_0900_ai_ci不区分) 对
DATETIME字段用
>或
时,注意时区和微秒精度(MySQL 5.6.4+ 支持 <code>.u微秒,但索引可能无法精确命中)
IN、BETWEEN、LIKE、REGEXP 的适用与陷阱
这些运算符语义更强,但性能和行为差异大:
IN支持常量列表或子查询,但子查询返回多列或
NULL会导致整个条件为
UNKNOWN;若列表超千项,建议改用临时表 + JOIN
BETWEEN a AND b是闭区间,等价于
col >= a AND col ,对日期要小心隐式截断(如 <code>'2023-10-01' BETWEEN '2023-10-01' AND '2023-10-01'会命中当天 00:00:00,但漏掉该日其他时间)
LIKE中
%和
_是通配符,前导
%(如
LIKE '%abc')无法使用 B+Tree 索引;若需全文检索,应改用
FULLTEXT索引 +
MATCH ... AGAINST
REGEXP功能强但性能差,不走索引,且 MySQL 的正则引擎不支持后向引用、贪婪控制等高级特性;简单模式尽量用
LIKE替代
逻辑运算符(AND、OR、NOT)与括号优先级
它们控制多个条件的组合方式,但容易因优先级出错:
AND优先级高于
OR,
WHERE a = 1 OR b = 2 AND c = 3实际等价于
a = 1 OR (b = 2 AND c = 3),不是
(a = 1 OR b = 2) AND c = 3
NOT对
IN、
LIKE、
BETWEEN都有效,但
NOT IN (1, 2, NULL)会永远返回空结果——因为
col NOT IN (1, 2, NULL)等价于
col != 1 AND col != 2 AND col != NULL,而最后一项恒为
UNKNOWN复杂条件务必用括号显式分组,尤其混用
AND/
OR时,别依赖记忆优先级
IS NULL、IS NOT NULL、COALESCE 与空值处理
MySQL 中
NULL不是值,而是“缺失值”标记,所有涉及
NULL的比较都会返回
UNKNOWN: 必须用
IS NULL或
IS NOT NULL判断,
= NULL、
NULL、
IN (NULL)全无效
COALESCE(col, 'default')常用于替代
NULL后再比较,但要注意:如果
col是字符串类型而
'default'是数字,可能触发隐式类型转换,导致索引失效 函数包装字段会阻止索引使用,例如
WHERE YEAR(create_time) = 2023无法走
create_time索引,应改写为
create_time >= '2023-01-01' AND create_time
真正麻烦的从来不是“有哪些运算符”,而是同一个运算符在不同数据类型、SQL 模式(如
STRICT_TRANS_TABLES)、索引结构下表现不一致。写完 WHERE 条件后,务必用
EXPLAIN看执行计划,而不是只看结果对不对。
