MySQL 正则表达式查询(REGEXP)全解
在 MySQL 中,正则表达式查询 通过 REGEXP 关键字实现,相比普通的 LIKE 模糊查询,它支持更强大的模式匹配(如开头 / 结尾、重复次数、范围匹配等)。
本文围绕图片中的 8 大核心场景,从基础到进阶,用极简代码 + 场景说明,带你彻底掌握 MySQL 正则查询。
一、核心语法与关键字
1. 基本语法
sql
SELECT 字段 FROM 表 WHERE 字段 REGEXP '正则表达式';
REGEXP:核心关键字,返回1(匹配成功)或0(匹配失败)NOT REGEXP:反向匹配,查询不满足条件的结果- 语法规则:遵循 MySQL 正则语法(与 PCRE 类似,但有少量差异)
2. 图片核心知识点对应
| 图片序号 | 正则关键字 | 功能 |
|---|---|---|
| (1) | ^ |
匹配以特定字符 / 字符串开头 |
| (2) | $ |
匹配以特定字符 / 字符串结尾 |
| (3) | . |
匹配任意单个字符(包括空格) |
| (4) | * / + |
匹配多个字符 :* 表示 0 个及以上,+ 表示 1 个及以上 |
| (5) | 字符串 | 直接匹配指定字符串存在 |
| (6) | [] |
匹配指定字符集合中的任意一个 |
| (7) | [^] |
匹配不在指定集合中的字符 |
| (8) | {n} / {n,m} |
指定字符出现的次数范围 |
二、准备测试数据
创建一张学生表 student,用于所有示例:
sql
CREATE TABLE student (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
email VARCHAR(30) NOT NULL,
phone VARCHAR(20) NOT NULL
);
INSERT INTO student (name, email, phone) VALUES
('张三', 'zhangsan@test.com', '13812345678'),
('李四', 'lisi@163.com', '13987654321'),
('王五', 'wangwu@qq.com', '15000001111'),
('赵六', 'zhaoliu@abc.com.cn', '18622223333'),
('孙七', 'sunqi@test.com', '17799998888');
三、核心场景详解 + 代码示例
1. (1) 查询以特定字符开头(^)
核心逻辑
^ 表示匹配行的开头,即字段值必须以该字符 / 字符串开始。
代码示例
sql
-- 查询姓名以'张'开头的学生
SELECT * FROM student WHERE name REGEXP '^张';
-- 查询邮箱以'zh'开头的学生
SELECT * FROM student WHERE email REGEXP '^zh';
结果说明
^张:只匹配姓名第一个字是 "张" 的记录(张三)。^zh:只匹配邮箱第一个字符是 "zh" 的记录(zhangsan@test.com)。
2. (2) 查询以特定字符结尾($)
核心逻辑
$ 表示匹配行的结尾,即字段值必须以该字符 / 字符串结束。
代码示例
sql
-- 查询邮箱以'com'结尾的学生
SELECT * FROM student WHERE email REGEXP 'com$';
-- 查询姓名以'六'结尾的学生
SELECT * FROM student WHERE name REGEXP '六$';
结果说明
com$:匹配邮箱最后三个字符是 "com" 的记录(李四、王五、赵六)。六$:匹配姓名最后一个字是 "六" 的记录(赵六)。
3. 匹配任意单个字符(.)
核心逻辑
. 是通配符,匹配任意一个字符 (包括空格),注意与 LIKE 的 _ 区分。
代码示例
sql
-- 查询姓名为"张_"的学生(张后面跟任意一个字)
SELECT * FROM student WHERE name REGEXP '张.';
-- 查询邮箱包含'@...com'(@和com之间有任意字符)
SELECT * FROM student WHERE email REGEXP '@.com';
结果说明
张.:匹配姓名长度为 2,且第一个字是 "张" 的记录(张三)。@.com:匹配@和com之间有且仅有一个字符的邮箱(如@1.com、@q.com)。
4. 匹配多个字符(* 和 +)
核心逻辑
*:匹配前面的字符 0 次或多次。+:匹配前面的字符 1 次或多次(至少出现一次)。
代码示例
sql
-- 查询姓名以'张'开头,后面跟任意字符(0个及以上)
SELECT * FROM student WHERE name REGEXP '张.*';
-- 查询邮箱包含'test',且前面至少有1个字符
SELECT * FROM student WHERE email REGEXP '.+test';
结果说明
张.*:匹配所有以 "张" 开头的姓名(张三)。.+test:匹配 "test" 前面至少有一个字符的邮箱(孙七的sunqi@test.com)。
5. 匹配指定字符串(直接写字符串)
核心逻辑
如果正则中写普通字符串,MySQL 会判断该字段是否包含这个子串。
代码示例
sql
-- 查询姓名中包含'三'的学生
SELECT * FROM student WHERE name REGEXP '三';
-- 查询邮箱中包含'163'的学生
SELECT * FROM student WHERE email REGEXP '163';
结果说明
三:匹配姓名中只要含有 "三" 字的记录(张三)。163:匹配邮箱中含有 "163" 子串的记录(李四)。
6. 匹配指定字符集合中的任意一个([])
核心逻辑
[字符集] 表示匹配集合中的任意一个字符。
代码示例
sql
-- 查询姓名中包含'张'或'李'的学生
SELECT * FROM student WHERE name REGEXP '[张李]';
-- 查询电话中第二位是'3'或'9'的学生
SELECT * FROM student WHERE phone REGEXP '^.(3|9)'; -- 或用 [39]
结果说明
[张李]:匹配姓名中含有 "张" 或 "李" 的记录(张三、李四)。^.(3|9):匹配电话第二位是 3 或 9 的记录(张三、李四)。
7. 匹配指定字符以外的字符([^])
核心逻辑
[^字符集] 表示匹配不在该集合中的任意一个字符。
代码示例
sql
-- 查询姓名中不包含'张'的学生
SELECT * FROM student WHERE name REGEXP '[^张]';
-- 查询电话中第二位不是'3'的学生
SELECT * FROM student WHERE phone REGEXP '^.[^3]';
结果说明
[^张]:匹配姓名中不含 "张" 字的记录(李四、王五、赵六、孙七)。^.[^3]:匹配电话第二位不是 3 的记录(王五、赵六、孙七)。
8. 指定字符出现次数({n} / {n,m})
核心逻辑
{n}:匹配前面的字符恰好出现 n 次。{n,}:至少出现 n 次。{n,m}:出现次数在 n 到 m 之间。
代码示例
sql
-- 查询姓名恰好是2个字的学生(正则:任意字符出现2次)
SELECT * FROM student WHERE name REGEXP '^.{2}$';
-- 查询电话中数字'1'连续出现至少2次的记录
SELECT * FROM student WHERE phone REGEXP '1{2,}';
结果说明
^.{2}$:匹配长度为 2 的姓名(张三、李四、王五、赵六、孙七)。1{2,}:匹配电话中连续两个及以上 "1" 的记录(张三、李四、王五、赵六、孙七)。
四、综合实战:复杂正则查询
sql
-- 需求:查询一班(假设姓名对应班级)中,邮箱以'test'开头或结尾,且分数>80的学生
-- 注:此处用name模拟班级条件
SELECT
s.name,
s.email,
sc.score
FROM student s
JOIN score sc ON s.id = sc.stu_id
WHERE
(s.email REGEXP '^test' OR s.email REGEXP 'test$')
AND sc.score > 80;
五、核心注意事项(避坑指南)
1. REGEXP 与 LIKE 的区别
| 特性 | LIKE |
REGEXP |
|---|---|---|
| 匹配范围 | 仅支持简单的 %(任意)和 _(单个) |
支持完整正则语法 |
| 默认规则 | 匹配整个字段 | 匹配字段的任意位置 (若要全匹配需加 ^$) |
| 性能 | 一般 | 一般(复杂正则会全表扫描) |
六、核心总结
- 核心关键字 :
REGEXP(匹配)、NOT REGEXP(不匹配)。 - 8 大核心场景 :
^开头,$结尾。.任意单字符,*任意多字符,+至少 1 个字符。[]任意一个,[^]排除。{n}精确次数,{n,m}范围次数。
- 使用场景:复杂数据筛选、报表统计、数据清洗(如手机号、邮箱格式校验)。
- 注意 :多表复杂查询中,别名 (
s.) 配合正则使用,代码更清晰。