不能直接匹配。MySQL默认不区分大小写,但尾部空格参与比较,'小%'无法匹配存储为'小 '(带空格)的值;需用TRIM()清理或显式指定校对规则如COLLATE utf8mb4_0900_as_cs。

WHERE name LIKE '小%' 能否匹配带空格或大小写不一致的值?
不能直接匹配。MySQL 默认的 utf8mb4_general_ci 校对规则不区分大小写,但会把尾部空格当作有效字符参与比较;如果字段是 CHAR 类型,DBMS 可能自动补空格,导致 '小%' 匹配失败——因为实际存储的是 '小 '(带空格),而 '小%' 无法匹配结尾空格后的任意字符。
常见错误现象:SELECT * FROM students WHERE name LIKE '小%'; 查不到明明以“小”开头的记录。
- 先用
SELECT name, LENGTH(name), HEX(name) FROM students WHERE name LIKE '小%' OR name LIKE '小% ';检查是否含不可见空格或全角空格 - 稳妥做法是统一清理:用
TRIM()或RTRIM()配合查询,例如WHERE TRIM(name) LIKE '小%' - 若需严格大小写匹配(如 PostgreSQL 或 MySQL 8.0+),显式指定校对规则:
WHERE name LIKE 'X%' COLLATE utf8mb4_0900_as_cs
LIKE 'A%' 和 LIKE '%A' 的性能差异为什么这么大?
因为只有前缀匹配(LIKE 'A%')可能走索引,后缀或中缀匹配(LIKE '%A'、LIKE '%A%')基本触发全表扫描。
原因在于 B+ 树索引按字典序组织,能快速定位「以 A 开头」的键范围,但无法跳过前导通配符去查找「结尾为 A」的键。
- 确认是否命中索引:在 MySQL 中执行
EXPLAIN SELECT * FROM users WHERE username LIKE 'admin%';,看key列是否非 NULL - 避免
NOT LIKE 'A%':它通常也无法利用索引,不如改用正向条件 +NOT IN子查询(且子查询需排除 NULL) - 若必须查后缀,可考虑生成冗余列(如
username_reversed),存反向字符串并建索引,查时用WHERE username_reversed LIKE 'nimda%'
想排除多个固定开头,该用 NOT LIKE 还是 LEFT() + NOT IN?
用 LEFT(col, 1) NOT IN ('A', 'B', 'C') 更可靠,也更容易走索引。
NOT LIKE 'A%' AND NOT LIKE 'B%' AND NOT LIKE 'C%' 不仅难读,还大概率让优化器放弃使用索引,尤其当字段基数高、过滤比例小时。
- 若开头长度不固定(如要排除「支付宝」「微信」开头),改用
NOT (col LIKE '支付宝%' OR col LIKE '微信%'),语义清晰且部分版本优化器能下推 - 注意 NULL:
LEFT(col, 1)对 NULL 返回 NULL,所以LEFT(col, 1) NOT IN ('A','B')会漏掉所有col IS NULL行;补上OR col IS NULL或用COALESCE(LEFT(col, 1), '') NOT IN ('A','B') - MySQL 8.0+ 支持函数索引,可直接建
CREATE INDEX idx_first_char ON t ((LEFT(name, 1)));
LIKE '[明军]' 这种写法在 MySQL 里根本不能用
方括号语法([明军])是 SQL Server / Access 的特性,MySQL 不支持。直接执行会报错:ERROR 1064 (42000): You have an error in your SQL syntax。
MySQL 中等价写法只有两种:
- 用
REGEXP:例如WHERE name REGEXP '^.[明军]$'(结尾是明或军),但性能差,无法走索引 - 更推荐用
RIGHT(name, 1) IN ('明', '军'),配合函数索引(MySQL 8.0+)或冗余列提升效率 - 若要「开头为明或军」,直接
LEFT(name, 1) IN ('明', '军')即可,简洁且可优化
真正容易被忽略的是校对规则对中文排序的影响——比如 utf8mb4_unicode_ci 会把「张」和「章」视为等效,而 utf8mb4_bin 则逐字节比对。过滤中文开头时,务必确认当前 collation 是否符合业务语义。

















