在处理数据库查询时,我们经常会遇到一些精准、复杂且灵活 的匹配场景:"如何校验客户录入的邮箱或手机号格式是否正确?"或 "如何筛选出名字以字母开头、中间包含特殊符号的用户名?"。面对这样的需求,传统的 LIKE 运算符配合 % 或 _ 通配符显得束手无策,而正则表达式(Regular Expression)就是你的终极武器。
文章目录
-
- [一、 正则表达式基础](#一、 正则表达式基础)
-
- [1.1 基础语法](#1.1 基础语法)
- [二、 基础语法示例](#二、 基础语法示例)
-
- [2.1 基础匹配](#2.1 基础匹配)
- [2.2 逻辑"或"匹配:管道符(|)](#2.2 逻辑“或”匹配:管道符(|))
- [2.2 字符集匹配:方括号([])](#2.2 字符集匹配:方括号([]))
- [2.3 范围匹配:连字符(-)](#2.3 范围匹配:连字符(-))
- [2.4 锚点:^ and ](#2.4 锚点:^ and )
- [三、 高阶匹配规则](#三、 高阶匹配规则)
-
- [3.1 特殊字符的转义(\)](#3.1 特殊字符的转义(\))
- [3.2 预定义字符类](#3.2 预定义字符类)
- [3.3 重复匹配(限定符)](#3.3 重复匹配(限定符))
- [四、 注意事项](#四、 注意事项)
一、 正则表达式基础
正则表达式是用于匹配文本的特殊字符串模式,如果说 通配符 是"模糊搜索",那么 正则表达式 就是"结构化匹配"。
1.1 基础语法
在 MySQL 中,正则表达式使用 LIKE 的语句非常相似,只是将关键字 LIKE 替换为了 REGEXP(或RLIKE,这两个是同义词):
sql
WHERE column_name REGEXP 'pattern'
或
WHERE column_name RLIKE 'pattern'
regexp 关键字告诉MySQL,后面的字符串是一个"正则表达式",要按这个模式匹配。
二、 基础语法示例
我们这里用MySQL的示例数据库Sakila作演示。
2.1 基础匹配
最基础的匹配就是直接跟一个字符串,这会返回所有包含此字符串的结果:
示例: 查找title包含"ACADEMY"的记录。
sql
SELECT title FROM film
WHERE title REGEXP 'ACADEMY';

这里的效果和 LIKE '%ACADEMY%'是一样的,但是正则表达式不需要通配符。
2.2 逻辑"或"匹配:管道符(|)
如果你想同时搜索多个可能的关键词,可以使用 |。
示例: 查找标题中包含 "ACADEMY" 或 "DINOSAUR" 的电影。
sql
SELECT title FROM film
WHERE title REGEXP 'ACADEMY|DINOSAUR';

2.2 字符集匹配:方括号([])
[] 匹配集合中的任意单个字符。
示例: 查找电影标题中包含 "ABA"或 "ABE" 的记录。
sql
SELECT title FROM film WHERE title REGEXP 'AB[AE]';

- 反向匹配 :
[^ABC]表示匹配不在集合中的任意字符。
2.3 范围匹配:连字符(-)
当[]中包含很多值,并且形成一个范围时,为了简化书写,可以使用连字符定义范围。例如[0123456789]表示匹配任意数字,可以简写为[0-9],同理,[a-z]:匹配任意小写字母。
示例: 查找时长在110~119分钟的电影。
sql
SELECT title, length FROM film
WHERE length REGEXP '11[0-9]';

2.4 锚点:^ and $
正则表达式的^和$分别代表匹配开头和匹配结尾:
示例: '^BA'表示仅匹配以BA开头的电影:
sql
SELECT title FROM film
WHERE title REGEXP '^BA';

示例: 'TED$'表示仅匹配以TED结尾的电影:
sql
SELECT title FROM film
WHERE title REGEXP 'TED$';

精确匹配: 如果在字符串的开头和结尾分别加上^和$,则代表精确匹配:
示例: '^IRON MOON$' 表示精确匹配电影名为"IRON MOON"的电影
sql
SELECT title FROM film
WHERE title REGEXP '^IRON MOON$';

三、 高阶匹配规则
3.1 特殊字符的转义(\)
在正则表达式中,.、-、[ 等字符有特殊含义。如果你想匹配这些字符本身,必须进行转义。MySQL 中需要使用双反斜杠 \\进行转移。
- 示例:查询电影rating包含'-'的记录
sql
SELECT title, rating FROM film
WHERE rating REGEXP '\\-';

3.2 预定义字符类
MySQL 预置了一些字符类,让 SQL 语句更具可读性,其等价写法如下:
| 字符类 | 含义 | 等价写法 |
|---|---|---|
[:digit:] |
任意数字 | [0-9] |
[:alpha:] |
任意字母 | [a-zA-Z] |
[:alnum:] |
任意字母数字 | [0-9a-zA-Z] |
[:space:] |
任意空白字符 | 空格/制表符等 |
3.3 重复匹配(限定符)
限定符用于控制前一个字符出现的次数:
| 限定符 | 含义 | 示例 | 匹配结果 |
|---|---|---|---|
* |
0次或多次 | a* |
(空), a, aa, aaa |
+ |
1次或多次 | a+ |
a, aa, aaa |
? |
0次或1次 | a? |
(空), a |
{n} |
恰好 n 次 | [0-9]{3} |
123, 456 (连续三位数字) |
- 示例:查询以3位数字开头,后面接1个空格的地址:
sql
SELECT address FROM address
where address REGEXP '^[:digit:]{3} ';

四、 注意事项
正则表达式是 MySQL 工具箱中的"瑞士军刀",但它也有代价,请记住以下原则:
- 优先使用 LIKE :简单的匹配不要使用正则表达式,
LIKE的性能在简单场景下远高于REGEXP。 - 避免在开头匹配:类似于通配符,如果正则表达式以模糊匹配开头,通常无法利用索引。
- 大小写敏感 :MySQL 默认不区分大小写。如果需要区分,请使用
REGEXP BINARY。- 例如
WHERE title REGEXP BINARY 'apple'(仅匹配小写)。
- 例如