WHERE 子句里用 = 和 的区别必须分清
MySQL 中
=是常规等值判断,但遇到
NULL会返回
UNKNOWN(即不匹配),而 是“空值安全等号”,
NULL NULL返回
TRUE。实际查数据时如果字段允许为
NULL,又想把空值也纳入条件,用
=会漏掉记录。
常见错误现象:
SELECT * FROM user WHERE phone = NULL查不到任何结果,哪怕表里真有
phone为
NULL的行。 查明确为
NULL的数据,写成
WHERE phone IS NULL或
WHERE phone NULL查非空且等于某个值的,仍用
=,比如
WHERE status = 'active'做参数化查询时(如 PHP PDO),绑定
NULL值后,底层可能生成
= ?,此时若字段含空值,逻辑就和预期不符 —— 得确认驱动是否自动转成
?,否则手动改写
字符串模糊匹配别只靠 LIKE,注意 ESCAPE 和大小写
LIKE看似简单,但
%和
_是通配符,如果要查真实包含下划线的用户名(如
'user_name'),直接写
WHERE name LIKE '%_name%'会误匹配
'username'、
'usename'等。 指定转义字符:加
ESCAPE '\'后,写成
WHERE name LIKE '%\_name%' ESCAPE '\'大小写敏感性取决于字段的 collation,
utf8mb4_bin下
'A' != 'a',而
utf8mb4_general_ci默认忽略大小写;不确定时用
BINARY强制:
WHERE BINARY name = 'Admin'性能提示:前导通配符(如
LIKE '%abc')无法走索引,尽量用
LIKE 'abc%'或考虑全文索引、生成列 + 普通索引
多个条件组合时 AND/OR 优先级容易出错
MySQL 中
AND优先级高于
OR,没加括号时,
WHERE status = 'active' OR type = 'vip' AND level > 5实际等价于
WHERE status = 'active' OR (type = 'vip' AND level > 5),而不是你以为的
(status = 'active' OR type = 'vip') AND level > 5。 所有含
OR的复合条件,只要逻辑不是纯线性叠加,一律显式加括号 用
IN替代一长串
OR:
WHERE id IN (1, 5, 9, 12)更清晰,也更易维护 注意
IN对
NULL的处理:
WHERE id IN (1, 2, NULL)整个条件恒为
FALSE,因为
id = NULL永远不成立 —— 如果需要兼容空值,拆开写或用
IS NULL
WHERE 中函数操作会让索引失效,得看执行计划
写
WHERE YEAR(create_time) = 2023看似直观,但 MySQL 无法用
create_time上的索引,因为函数改变了字段原始值。同理,
UPPER(name) = 'JOHN'、
DATE(update_at) = '2024-06-01'都有这个问题。 改写为范围查询:用
WHERE create_time >= '2023-01-01' AND create_time对固定格式转换,可建函数索引(MySQL 8.0+):
CREATE INDEX idx_upper_name ON user ((UPPER(name)))务必用
EXPLAIN验证:重点关注
type(应为
ref/
range)、
key(是否用了预期索引)、
rows(扫描行数是否合理)
复杂点在于,有些隐式转换更难察觉,比如字段是
VARCHAR却传入数字参数:
WHERE mobile = 13812345678,MySQL 会把字段转成数字比对,同样导致索引失效 —— 这类问题在线上慢查日志里才容易暴露出来。
