首页 / MySQL 入门教程 / 模糊查询 LIKE 与正则表达式

MySQL 入门教程

模糊查询 LIKE 与正则表达式

本教程共 46 篇 · 第 21 篇 · 更新于 2026-07-30 · 约 10 分钟阅读

MySQLMySQL 入门教程LIKEREGEXP正则表达式通配符模糊查询

21. 模糊查询 LIKE 与正则表达式

本节目标:学会两种字符串模糊匹配方式,LIKE 通配符查询和 REGEXP 正则表达式查询,掌握通配符 % 和 _ 的用法、特殊字符转义、正则表达式常用语法,以及模糊查询的性能陷阱。

21.1 为什么需要模糊查询

前面的查询都是精确匹配,WHERE username = '张三' 只能查用户名恰好是”张三”的。但实际需求往往没那么精确:

  • “查所有姓张的用户”
  • “查邮箱以 @gmail.com 结尾的用户”
  • “查用户名里包含数字的”

这些场景就需要模糊查询。MySQL 提供了两种方式:LIKEREGEXP

21.2 LIKE 与通配符

LIKE 是最简单的模糊匹配方式,配合两个通配符使用:

通配符含义示例
%匹配任意数量字符(包括零个)'张%' 匹配”张”、“张三”、“张三丰”
_匹配单个字符'张_' 匹配”张三”,不匹配”张”或”张三丰”

开头匹配

-- 查所有姓张的用户
SELECT * FROM users WHERE username LIKE '张%';

% 在后面,表示”张”后面跟任意字符(或没有字符)。

结尾匹配

-- 查邮箱以 @gmail.com 结尾的用户
SELECT * FROM users WHERE email LIKE '%@gmail.com';

% 在前面,表示前面可以是任意字符。

中间包含

-- 查用户名里包含"三"的用户
SELECT * FROM users WHERE username LIKE '%三%';

两端都加 %,表示”三”可以在任意位置。

下划线通配符

-- 查用户名是两个字且第一个字是"张"的用户
SELECT * FROM users WHERE username LIKE '张_';

_ 只匹配一个字符,多了少了都不行。

Note

% 是”任意数量”(包括零个),_ 是”恰好一个”。区分这两个通配符是 LIKE 的核心。'张%' 能匹配”张”,但 '张_' 不能。

21.3 LIKE 的转义

如果查询的内容本身就包含 %_,怎么办?比如查邮箱里包含”user_name”的用户,_ 会被当成通配符。

ESCAPE 关键字指定转义字符:

-- 用反斜杠转义下划线
SELECT * FROM users WHERE email LIKE '%user\_name%' ESCAPE '\\';

\_ 表示字面意义的下划线,不再当通配符。MySQL 默认的转义字符就是 \,所以 ESCAPE '\\' 可以省略不写:

SELECT * FROM users WHERE email LIKE '%user\_name%';

转义 % 同理:

-- 查包含 50% 的内容
SELECT * FROM orders WHERE status LIKE '%50\%%';

这里第一个和第三个 % 是通配符,中间 \% 是字面意义的百分号。

Tip

转义字符默认是反斜杠 \。如果你的数据里反斜杠本身就是内容的一部分,可以用 ESCAPE 换一个字符,比如 ESCAPE '|',然后用 |% 表示字面百分号。

21.4 NOT LIKE

取反用 NOT LIKE

-- 查邮箱不是以 @gmail.com 结尾的用户
SELECT * FROM users WHERE email NOT LIKE '%@gmail.com';

21.5 REGEXP:正则表达式

LIKE 的通配符太简单了,复杂匹配搞不定。比如”查用户名以字母开头、后面跟数字”的,LIKE 写不了。这时候用 REGEXP(或 RLIKE,两者等价)。

基本语法:

SELECT * FROM users WHERE username REGEXP '正则模式';

正则表达式常用语法

语法含义示例
^匹配字符串开头'^张' 以”张”开头
$匹配字符串结尾'com$' 以”com”结尾
.匹配任意单个字符'张.' “张”后跟任意一个字符
[abc]匹配方括号中任意一个字符'[张李王]' 匹配”张”或”李”或”王”
[^abc]匹配不在方括号中的字符'[^0-9]' 匹配非数字字符
[a-z]匹配范围'[a-z]' 匹配小写字母
*前面的字符出现 0 次或多次'ab*' 匹配”a”、“ab”、“abbb”
+前面的字符出现 1 次或多次'ab+' 匹配”ab”、“abbb”,不匹配”a”
?前面的字符出现 0 次或 1 次'ab?' 匹配”a”或”ab”
{n}前面的字符出现 n 次'a{3}' 匹配”aaa”
{n,m}出现 n 到 m 次'a{2,4}' 匹配”aa”到”aaaa”
|'张|李' 匹配”张”或”李”
(abc)分组'(ab)+' 匹配”ab”、“abab”

实际示例

-- 查用户名以"张"开头的
SELECT * FROM users WHERE username REGEXP '^张';

-- 查用户名以"张"或"李"开头的
SELECT * FROM users WHERE username REGEXP '^[张李]';

-- 查邮箱以数字结尾的
SELECT * FROM users WHERE email REGEXP '[0-9]$';

-- 查用户名包含至少两个连续数字的
SELECT * FROM users WHERE username REGEXP '[0-9]{2}';

-- 查用户名是纯字母的
SELECT * FROM users WHERE username REGEXP '^[a-zA-Z]+$';

预定义字符类

MySQL 正则还支持一些预定义字符类,写起来更短:

类名含义等价于
[:digit:]数字[0-9]
[:alpha:]字母[a-zA-Z]
[:alnum:]字母和数字[a-zA-Z0-9]
[:space:]空白字符[ \t\n\r]
[:upper:]大写字母[A-Z]
[:lower:]小写字母[a-z]
-- 查用户名包含空格的
SELECT * FROM users WHERE username REGEXP '[[:space:]]';
Note

MySQL 的正则表达式默认是不区分大小写的。要区分大小写,用 REGEXP BINARYRLIKE BINARY

SELECT * FROM users WHERE email REGEXP BINARY '^[A-Z]';

21.6 LIKE vs REGEXP

对比项LIKEREGEXP
匹配能力简单(只有 % 和 _)强大(完整正则语法)
匹配方式整个字符串匹配部分匹配即可(除非用 ^ $)
性能略快略慢
可读性简单直观复杂模式可读性差
使用频率日常查询常用复杂匹配时用

一个重要区别:LIKE 是全字符串匹配LIKE '张' 只匹配恰好是”张”的。而 REGEXP 是部分匹配REGEXP '张' 匹配任何包含”张”的字符串。

-- LIKE:只匹配恰好是"张三"的
SELECT * FROM users WHERE username LIKE '张三';

-- REGEXP:匹配任何包含"张三"的
SELECT * FROM users WHERE username REGEXP '张三';

-- REGEXP 要全字符串匹配,需加锚点
SELECT * FROM users WHERE username REGEXP '^张三$';

21.7 模糊查询的性能问题

模糊查询是性能杀手,特别是 % 开头的查询。

前缀匹配可以走索引

-- 能走索引(如果 username 上有索引)
SELECT * FROM users WHERE username LIKE '张%';

因为 张% 匹配的是以”张”开头的,B+Tree 索引可以快速定位。

% 开头走不了索引

-- 走不了索引,全表扫描
SELECT * FROM users WHERE username LIKE '%三%';
SELECT * FROM users WHERE email LIKE '%@gmail.com';

% 在开头意味着不知道从哪开始找,索引帮不上忙,只能逐行扫描。数据量大时会很慢。

Warning

前缀模糊(%xxx)是慢查询的常见原因。几百万行的表上跑 LIKE '%关键词%',可能要几秒甚至几十秒。如果业务上确实需要全文搜索,考虑用全文索引(FULLTEXT INDEX)或外部搜索引擎(如 Elasticsearch)。

REGEXP 的性能

REGEXP 的性能比 LIKE 更差,几乎总是全表扫描。只有在数据量不大或确实需要复杂匹配时才用。

Tip

性能优化的一个思路:先用其他条件(走索引的精确匹配)缩小范围,再在小结果集上做模糊匹配:

-- 先用 status 过滤(走索引),再模糊匹配
SELECT * FROM orders
WHERE status = 'pending' AND remark LIKE '%加急%';

21.8 小结

LIKE 适合简单的前缀、后缀、包含匹配,REGEXP 适合复杂的模式匹配。核心记住:% 匹配任意数量字符,_ 匹配单个字符,正则用 ^$ 做全字符串匹配,特殊字符用 \ 转义。性能上,前缀匹配(xxx%)能走索引,% 开头的模糊匹配会全表扫描,慎用在大表上。下一章学排序和分页。