讲解

精确相等解决不了「名字里带某个字」「标题包含某关键词」这类需求,这时用 LIKE 做模式匹配。模式里有两个通配符:% 匹配任意长度的任意字符(包括零个字符),_ 匹配恰好一个任意字符。WHERE title LIKE '%入门%' 匹配标题中任何位置含有「入门」的课程;WHERE name LIKE '张%' 匹配张姓学生;WHERE name LIKE '李_' 匹配「李某」这种两个字的名字。

匹配串里如果本身含有 % 或 _,需要用 ESCAPE 指定转义符:WHERE note LIKE '%50!%%' ESCAPE '!' 表示匹配字面上的 50%。日常查询很少用到,但搜索用户输入时这是必须的防护措施。

大小写行为各数据库不同,要特别留心:SQLite 的 LIKE 对 ASCII 字母不区分大小写('SQL 入门' LIKE '%sql%' 为真),但对中文等多字节字符仍是区分处理的;PostgreSQL 的 LIKE 完全区分大小写(另提供 ILIKE 做不区分匹配);MySQL 默认取决于字符集排序规则,通常不区分。写跨数据库的 SQL 时不要依赖 LIKE 的大小写行为。

示例

标题里包含「入门」的课程:

SELECT title, price FROM courses WHERE title LIKE '%入门%';

张姓的学生(% 在尾部,匹配任意后缀):

SELECT name, city FROM students WHERE name LIKE '张%';

用下划线匹配「两个字、姓李」的名字:

SELECT name FROM students WHERE name LIKE '李_';

常见坑

  • 以 % 开头的模式用不上索引:LIKE '%入门' 这种前通配查询只能全表扫描,数据量大时很慢。需要全文搜索时应使用数据库的全文索引(如 SQLite 的 FTS5)或专门的搜索引擎。
  • 依赖 LIKE 的大小写行为:同一条语句在 SQLite 不区分大小写、在 PostgreSQL 区分,迁移数据库后查询结果悄悄变化。跨库场景用 LOWER(title) LIKE '%sql%' 这类显式写法。
  • 忘记转义用户输入里的 % 和 _:用户搜索「50%」如果不转义,% 会被当成通配符,匹配结果远超预期。拼接 LIKE 模式前必须处理通配符。
  • 把 LIKE 当相等用:WHERE name LIKE '李明' 没有通配符时等价于 =,但白白多一次模式匹配开销,也让人误以为在做模糊匹配。精确匹配就用 =。

小结

LIKE 用 %(任意长度)和 _(单个字符)做模糊匹配,ESCAPE 处理字面通配符;大小写行为因数据库而异,前导 % 会让索引失效。下一节学习 IN 与 BETWEEN。