模糊匹配 LIKE 与 GLOB
本教程共 50 篇 · 第 23 篇 · 更新于 2026-07-31
23. 模糊匹配 LIKE 与 GLOB
本节目标:学完本章你能用
LIKE和GLOB写出带通配符的模糊查询,并清楚知道两套通配符怎么写、什么时候大小写敏感、两者该选哪一个。
为什么需要模糊匹配
前面我们在 WHERE 里做条件过滤,大多是用 = 做”完全相等”的判断,比如 WHERE name = 'Alice'。但真实场景里,你常常并不知道完整的值,只知道”大概长什么样”:
- 想找出所有名字里带”张”字的人;
- 想找出邮箱域名是某个后缀的账号;
- 想找出文件名以
.pdf结尾的记录; - 想找出车牌号第二位是某个字母的数据。
这种”按模式(pattern)去匹配,而不是按完整值去相等”的需求,就是模糊匹配,英文叫 pattern matching。SQLite 提供了两个做模糊匹配的运算符:LIKE 和 GLOB。它们都返回一个布尔结果(匹配成功为 1,失败为 0),通常放在 WHERE 子句里当过滤条件用。
Note重点提示:
LIKE和GLOB比较的是文本。users表的name、TEXT列,最适合用来演示;即使拿数字列(如age)去LIKE,SQLite 也会先把数字转成文本再比较,这属于动态类型带来的”灵活”,但结果以文本形态为准。
LIKE:最常用、对人最友好的模糊匹配
LIKE 只认识两个通配符:
%(百分号):代表”任意长度”的任意字符,包括零个字符。它相当于”随便多少字都行”。_(下划线):代表”恰好一个”任意字符。它相当于”这里必须占一个位置,但什么字都行”。
注意 SQLite 是动态类型的,列上写的 TEXT 只是类型亲和性(Type Affinity)的建议,实际存储类由值决定;不过 LIKE/GLOB 的匹配行为只看文本表示,所以理解成”在字符串上套模式”就够了。
下面是一些典型写法,假设我们用全局统一的 users 表:
sqlite> SELECT name FROM users WHERE name LIKE '张%';
sqlite> SELECT name FROM users WHERE name LIKE '%伟';
sqlite> SELECT name FROM users WHERE name LIKE '%小%';
sqlite> SELECT email FROM users WHERE email LIKE '%@gmail.com';
含义分别是:以”张”开头、以”伟”结尾、中间含”小”、邮箱以 @gmail.com 结尾。
再看 _ 的用法。假设想找”姓一个字、名是两个字、总共三个字”的名字:
sqlite> SELECT name FROM users WHERE name LIKE '__%' AND length(name) = 3;
这里 % 吃掉后面任意字符,_ 精确占一个位置。但要数清下划线个数容易出错,所以”长度固定为 N”的需求更推荐配合 length() 函数一起写,可读性更好。
LIKE 的大小写问题
LIKE 默认对 ASCII 英文字母是大小写不敏感的,也就是说 WHERE name LIKE 'alice' 能匹配到 Alice、ALICE、alice。这是因为 LIKE 默认使用 NOCASE 这种校对规则(Collation)来比较。但要特别注意:这种不敏感只覆盖 A–Z/a–z 这 26 个英文字母;对于中文、带声调的字母、或其他 Unicode 字符,LIKE 不一定不敏感,结果取决于数据库使用的校对规则。所以不要依赖 LIKE 去做”全语言大小写不敏感”,它只是英文友好。
想匹配真正的 % 或 _ 怎么办:ESCAPE
因为 % 和 _ 被当成通配符了,如果你真的想搜”包含下划线”的字符串(比如字段名 col_1),就得用 ESCAPE 子句声明一个”转义符”:
sqlite> SELECT * FROM users WHERE name LIKE 'col|_1' ESCAPE '|';
这里 | 被声明为转义符,|_ 中的 _ 就被当成普通下划线,而不是”任意单字符”通配符。这是 LIKE 才有的能力,GLOB 没有转义机制。
GLOB:更严格、类 Unix 的大小写敏感匹配
GLOB 的写法借鉴了 Unix/Linux 的”文件名通配”(glob),通配符是另一套:
*(星号):匹配任意长度任意字符,等价于LIKE的%。?(问号):匹配恰好一个任意字符,等价于LIKE的_。[...](方括号):匹配方括号里列出的”某一个”字符。例如[abc]匹配 a、b、c 中的任意一个;[a-z]匹配 a 到 z 的任意一个小写字母;[0-9]匹配任意数字。[^...](^ 开头):匹配”不在”方括号列表里的任意一个字符。例如[^0-9]匹配任意非数字字符。
一个关键差异:GLOB 永远是大小写敏感的,'Man*' 不会匹配 man*。
sqlite> SELECT name FROM users WHERE name GLOB '张*';
sqlite> SELECT name FROM users WHERE name GLOB '*伟';
sqlite> SELECT name FROM users WHERE name GLOB '[A-Z]*';
sqlite> SELECT email FROM users WHERE email GLOB '*[0-9]*@*';
最后一条表示”邮箱里 @ 之前的部分含有数字”。[...] 是 GLOB 的强项,用来做”字符集合 / 区间”匹配非常方便,而 LIKE 本身并不支持方括号语法(见下方常见坑)。
Tip实用技巧:什么时候选
GLOB?当你需要大小写敏感或者需要方括号字符集(比如”首字母必须是大写""不能含数字”)时,用GLOB。当你只是想做普通、对英文大小写不敏感的搜索(比如搜用户名、搜关键词),用LIKE更顺手,也更符合大多数人的直觉。
LIKE 与 GLOB 的区别对比
| 维度 | LIKE | GLOB |
|---|---|---|
| 多字符通配符 | % | * |
| 单字符通配符 | _ | ? |
字符集合 [abc]/[a-z] | 不支持 | 支持 |
排除集合 [^...] | 不支持 | 支持 |
| 大小写敏感 | 对 ASCII 英文不敏感 | 永远敏感 |
| 转义字符(ESCAPE) | 支持 | 不支持 |
| 风格来源 | SQL 标准通用 | Unix glob 风格 |
一句话记忆:LIKE 用 % 和 _、GLOB 用 * 和 ?;GLOB 多了一套方括号、且区分大小写。
性能与适用场景提醒
模糊匹配虽然好用,但有个代价:当模式以通配符开头(如 LIKE '%伟'、GLOB '*伟')时,SQLite 往往无法利用索引,只能逐行扫描整张表去比对。数据量小无所谓,数据量大时会明显变慢。如果业务上频繁要”后缀匹配”,可以考虑冗余存储一份反转后的字符串、或用专门的 FTS5 全文检索(本教程后续章节会讲)。
Warning常见坑:网上有些教程(如部分 runoob 内容)会写出
LIKE '[AB]%'这种带方括号的例句,那是 MySQL / SQL Server 的写法,在 SQLite 里并不成立。SQLite 的LIKE只认%和_两个通配符,方括号[...]是GLOB的专属语法。想在 SQLite 里做”首字母是 A 或 B”的匹配,请用GLOB '[AB]*',或者拆成LIKE 'A%' OR LIKE 'B%'。照搬错误写法会让你查不到本该查到的数据。
Warning常见坑:不要把”大小写不敏感”想当然地套到所有语言上。
LIKE只对 ASCII 英文字母默认不敏感;对中文或特殊字符是否不敏感,取决于表的校对规则(Collation)。需要严格区分大小写时,直接用GLOB更稳妥,不要赌LIKE的表现。
类比小结
把 LIKE 和 GLOB 想成两种”模糊搜人”的方式:
LIKE像是你跟前台说”帮我找姓张的、名字里带个伟字的”,前台对英文大小写比较宽容,你说alice他也把Alice叫来;GLOB像是你拿着一份严格的门禁规则,“首字母必须大写、不能含数字”,一字之差都不行,而且区分大小写毫不含糊,还支持”字符白名单/黑名单”(方括号)。
记住通配符的对应关系(%↔*、_↔?)、记住 GLOB 才支持方括号且永远大小写敏感、记住 LIKE 可用 ESCAPE 转义,模糊查询这一关就算过了。