where子句必须紧跟在select/update/delete后,基础写法为where column = value;字符串和日期须加单引号,NULL需用is null判断,多条件建议用括号明确逻辑,like前导通配符影响索引性能。

WHERE 子句的基本写法和常见错误
mysql 中 WHERE 子句必须紧跟在 SELECT、UPDATE 或 DELETE 语句之后,用于过滤行。最基础的结构是:WHERE column = value。容易出错的是把字符串值不加引号,比如写成 WHERE name = zhangsan(正确应为 WHERE name = 'zhangsan'),这会导致 MySQL 报错 Unknown column 'zhangsan' in 'where clause'。
- 数字类型字段可不加引号,如
id = 123 - 字符串、日期类型必须用单引号包裹,如
name = 'Alice'、created_at = '2024-01-01' -
NULL值不能用=判断,必须用IS NULL或IS NOT NULL - 多个条件用
AND/OR连接,注意运算优先级;建议用括号明确逻辑,如WHERE (status = 'active') AND (score > 80)
LIKE 模糊匹配要注意转义和性能
LIKE 是 WHERE 中高频但易误用的操作符。通配符 %(任意长度)和 _(单个字符)必须配合引号使用,例如 WHERE username LIKE 'admin%'。如果要查本身含 % 的字面量,得用 ESCAPE 指定转义符:
WHERE comment LIKE '%100% off%' ESCAPE ''
- 前导通配符(如
LIKE '%abc')无法走索引,查询会变慢 - 想查固定前缀时尽量用
LIKE 'abc%',这样能命中 B+ 树索引 - 区分大小写取决于字段的 collation;若需强制不区分,可用
LOWER(column) LIKE LOWER('ABC%'),但会丢失索引
IN 和 BETWEEN 的适用边界
IN 适合枚举少量离散值,BETWEEN 专用于闭区间连续范围。二者语法简洁,但行为差异明显:
-
WHERE id IN (1, 5, 9)等价于WHERE id = 1 OR id = 5 OR id = 9;值过多(如超千个)会导致解析慢,建议分批或改用临时表 -
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31'包含两端,等价于>= AND ;注意时间字段含时分秒时,<code>'2024-12-31'实际是'2024-12-31 00:00:00',可能漏掉当天其他时间的数据 -
BETWEEN对字符串也有效,但按字符集排序规则比较,比如WHERE name BETWEEN 'A' AND 'M'可能不包含带重音的 ‘Á’
WHERE 条件中函数调用的隐患
在 WHERE 左侧对字段使用函数(如 WHERE YEAR(created_at) = 2024)会让该字段无法使用索引,即使 created_at 上建了索引也没用。
- 应改为范围写法:
WHERE created_at >= '2024-01-01' AND created_at - 类似地,
WHERE UPPER(name) = 'JOHN'应改为WHERE name = 'JOHN'并确保字段 collation 不区分大小写(如utf8mb4_0900_as_cs区分,utf8mb4_0900_ai_ci不区分) - 只有当函数作用于常量一侧时才安全,如
WHERE status = UPPER('active')
实际写 WHERE 时,最常被忽略的是:日期字段没考虑时区和精度、字符串比较未确认 collation、以及对字段用函数导致索引失效——这些不会报错,但会让查询从毫秒变秒级。