SQL 中的正则表达式
正则表达式
正则表达式(Regular Expression,简称 Regex 或 Regexp)是一种用于匹配字符串中字符组合的模式。它们在文本处理、数据验证和搜索操作中非常有用。以下是一些常见的正则表达式及其用途:
一. 常见的正则表达式
1. 字符类
字符类用于匹配特定的字符集合。
-
.
:匹配任何单个字符(除换行符外)。- 示例:
a.b
匹配a
后面跟着任何字符,再跟着b
,如a1b
、a-b
。
- 示例:
-
[abc]
:匹配方括号内的任意一个字符。- 示例:
[abc]
匹配a
、b
或c
。
- 示例:
-
[^abc]
:匹配不在方括号内的任意一个字符。- 示例:
[^abc]
匹配除a
、b
和c
之外的任何字符。
- 示例:
-
[a-z]
:匹配指定范围内的任意一个字符。- 示例:
[a-z]
匹配任何小写字母。
- 示例:
-
[A-Z]
:匹配任何大写字母。- 示例:
[A-Z]
匹配任何大写字母。
- 示例:
-
[0-9]
:匹配任何数字。- 示例:
[0-9]
匹配任何单个数字。
- 示例:
2. 预定义字符类
预定义字符类是一些常用的字符类的简写形式。
-
\d
:匹配任何数字,等价于[0-9]
。- 示例:
\d
匹配任何单个数字。
- 示例:
-
\D
:匹配任何非数字字符,等价于[^0-9]
。- 示例:
\D
匹配任何非数字字符。
- 示例:
-
\s
:匹配任何空白字符,包括空格、制表符、换行符等。- 示例:
\s
匹配任何空白字符。
- 示例:
-
\S
:匹配任何非空白字符。- 示例:
\S
匹配任何非空白字符。
- 示例:
-
\w
:匹配任何字母数字字符,等价于[a-zA-Z0-9_]
。- 示例:
\w
匹配任何字母数字字符或下划线。
- 示例:
-
\W
:匹配任何非字母数字字符。- 示例:
\W
匹配任何非字母数字字符。
- 示例:
3. 边界匹配
边界匹配用于匹配字符串的开始或结束位置。
-
^
:匹配字符串的开始位置。- 示例:
^abc
匹配以abc
开头的字符串。
- 示例:
-
$
:匹配字符串的结束位置。- 示例:
abc$
匹配以abc
结尾的字符串。
- 示例:
-
\b
:匹配单词边界。- 示例:
\bword\b
匹配完整的单词word
,而不是word
的子字符串。
- 示例:
4. 量词
量词用于指定前面的字符或字符类可以出现的次数。
-
*
:匹配前面的字符或字符类 0 次或多次。- 示例:
a*
匹配 0 个或多个a
,如a
、aa
、aaa
或空字符串。
- 示例:
-
+
:匹配前面的字符或字符类 1 次或多次。- 示例:
a+
匹配 1 个或多个a
,如a
、aa
、aaa
,但不匹配空字符串。
- 示例:
-
?
:匹配前面的字符或字符类 0 次或 1 次。- 示例:
a?
匹配 0 个或 1 个a
,如a
或空字符串。
- 示例:
-
{n}
:匹配前面的字符或字符类恰好n
次。- 示例:
a{3}
匹配恰好 3 个a
,如aaa
。
- 示例:
-
{n,}
:匹配前面的字符或字符类至少n
次。- 示例:
a{3,}
匹配 3 个或更多a
,如aaa
、aaaa
。
- 示例:
-
{n,m}
:匹配前面的字符或字符类至少n
次,但不超过m
次。- 示例:
a{2,4}
匹配 2 到 4 个a
,如aa
、aaa
、aaaa
。
- 示例:
5. 分组和捕获
分组和捕获用于将正则表达式的一部分分组,并捕获匹配的内容。
-
()
:分组和捕获。- 示例:
(abc)
匹配abc
,并捕获匹配的内容。
- 示例:
-
(?:...)
:非捕获分组。- 示例:
(?:abc)
匹配abc
,但不捕获匹配的内容。
- 示例:
6. 选择
选择用于匹配多个模式中的一个。
|
:选择。- 示例:
abc|def
匹配abc
或def
。
- 示例:
7. 贪婪和非贪婪
量词的贪婪和非贪婪模式决定了匹配的长度。
-
贪婪模式:默认情况下,量词是贪婪的,尽可能多地匹配字符。
- 示例:
a+
匹配尽可能多的a
。
- 示例:
-
非贪婪模式:在量词后加
?
,使其变为非贪婪模式,尽可能少地匹配字符。- 示例:
a+?
匹配尽可能少的a
。
- 示例:
8. 断言
断言用于指定匹配的条件,但不消耗字符。
-
前瞻断言:
- 正前瞻:
(?=...)
,匹配后面跟着指定模式的字符。- 示例:
abc(?=def)
匹配abc
,但只有在其后面跟着def
时才匹配。
- 示例:
- 负前瞻:
(?!...)
,匹配后面不跟着指定模式的字符。- 示例:
abc(?!def)
匹配abc
,但只有在其后面不跟着def
时才匹配。
- 示例:
- 正前瞻:
-
后顾断言:
- 正后顾:
(?<=...)
,匹配前面跟着指定模式的字符。- 示例:
(?<=abc)def
匹配def
,但只有在其前面跟着abc
时才匹配。
- 示例:
- 负后顾:
(?<!...)
,匹配前面不跟着指定模式的字符。- 示例:
(?<!abc)def
匹配def
,但只有在其前面不跟着abc
时才匹配。
- 示例:
- 正后顾:
示例
假设有一个字符串 123abc456def789
,我们想匹配其中的数字和字母组合。
-
匹配数字:
\d+
- 匹配结果:
123
、456
、789
- 匹配结果:
-
匹配字母:
[a-z]+
- 匹配结果:
abc
、def
- 匹配结果:
-
匹配数字和字母组合:
\d+[a-z]+
- 匹配结果:
123abc
、456def
- 匹配结果:
二. 使用语法
在 MySQL 中,可以使用 REGEXP
或 RLIKE
操作符来使用正则表达式。
语法:
REGEXP
SELECT column1, column2
FROM table_name
WHERE column1 REGEXP 'pattern';
RLIKE
SELECT column1, column2, ...
FROM table_name
WHERE column_name RLIKE 'pattern';
三. 使用 LIKE
和正则表达式的区别
-
LIKE
操作符:- 适用于简单的模式匹配,支持
%
和_
两个通配符。 - 性能较好,适用于大多数简单的文本匹配需求。
- 适用于简单的模式匹配,支持
-
正则表达式:
- 适用于复杂的模式匹配,支持更广泛的模式匹配功能。
- 性能可能稍差,但在处理复杂模式时非常强大。
示例
假设有一个 employees
表,包含以下数据:
1 | Alice | Smith | 60000 | 101 |
2 | Bob | Johnson | 70000 | 101 |
3 | Charlie | Brown | NULL | 102 |
4 | David | Davis | 80000 | 102 |
5 | Eve | White | 90000 | 103 |
假设我们想查询名字以字母 "A" 开头,且名字长度为 5 个字符的员工。使用 LIKE
操作符可以这样写:
SELECT *
FROM employees
WHERE first_name LIKE 'A____';
结果:
1 | Alice | Smith | 60000 | 101 |
使用正则表达式可以这样写:
SELECT *
FROM employees
WHERE first_name REGEXP '^A.{4}$';
结果:
1 | Alice | Smith | 60000 | 101 |
总结
LIKE
操作符:适用于简单的模式匹配,支持%
和_
通配符,性能较好。- 正则表达式:适用于复杂的模式匹配,支持更广泛的模式匹配功能,但性能可能稍差。