MySQL 正则表达式(Regexp)

⚡ 智能摘要

MySQL 正则表达式 (REGEXP) 将列值与通配符无法表达的灵活模式进行匹配。本文解释了 REGEXP 语法、RLIKE 同义词、所有支持的元字符、针对 myflixdb 数据库的更正查询示例以及新增的正则表达式函数。 MySQL 8.0.

  • 🔍 核心优势 OperaTOR: REGEXP 将列与模式进行比较,匹配则返回 1,而 RLIKE 是 REGEXP 的完全同义词。
  • 🧩 模式 Anchors: 插入符号 (^) 将匹配项锚定到值的开头,美元符号 ($) 将匹配项锚定到值的结尾。
  • 🔤 角色列表: [abcd] 匹配任何被括起来的字符,而 [^abcd] 从结果集中排除所有被括起来的字符。
  • 量词: 星号、加号和问号适用于它们前面的单个字符,而不是整个字符串。
  • 🛡️ 埃斯卡ping 规则: 在模式中,反斜杠必须重复出现,因为 MySQL 对字符串进行两次处理。
  • 🆕 版本变更: MySQL 8.0 版本移至 ICU 引擎,将 [[:<:]] 和 [[:>:]] 替换为 \b,并添加了 REGEXP_LIKE、REGEXP_REPLACE、REGEXP_SUBSTR 和 REGEXP_INSTR。
  • 性能说明: 正则表达式永远不会使用索引,因此,只要查询允许,就应该先使用索引条件筛选行。

是什么 MySQL 正则表达式?

MySQL 正则表达式 它可以帮助您搜索符合复杂条件的数据。正则表达式是一种描述您要查找的值的形状的模式,而不是值本身。

如果您已经与……合作过 MySQL 通配符你可能会问,既然 LIKE 函数也能得到类似的结果,为什么还要学习正则表达式呢?答案在于正则表达式的表达能力:通配符只能提供两个符号,而正则表达式可以在一个模式中描述字符范围、替代字符、重复字符以及单词位置。

既然目的已经明确,下一节将介绍您将在每个 REGEXP 查询中使用的语法。

正则表达式的基本语法

正则表达式的基本语法如下。

SELECT * FROM table_name
WHERE fieldname REGEXP 'pattern';

位置:

  • “SELECT语句” 是标准 选择语句.
  • “WHERE 字段名称” 是执行正则表达式的列的名称。
  • “REGEXP‘模式’” — REGEXP 是正则表达式运算符,“pattern”表示要匹配的模式。 RLIKE 是一个意念波· REGEXP 的同义词 并且返回相同的结果。为了避免与 LIKE 运算符混淆,最好使用正则表达式。

现在让我们来看一个实际例子。

SELECT * FROM `movies`
WHERE `title` REGEXP 'code';

上述查询会搜索所有包含单词“code”的电影标题。“code”出现在标题的开头、中间还是结尾都无关紧要。只要标题包含该模式,就会返回该行结果。

将值的开头与字符列表进行匹配

假设我们想要查找片名以 a、b、c 或 d 开头,后跟任意数量其他字符的电影。我们可以将字符列表与插入符号元字符结合使用来实现这一目标。

SELECT * FROM `movies`
WHERE `title` REGEXP '^[abcd]';

在以下位置执行上述脚本 MySQL 工作台 与 myflixdb 数据库进行比对,得到以下结果。

电影 ID 标题 导向器 发行年份 类别编号
4 Code 黑 埃德加·吉姆斯 2010
5 爸爸的小女孩 2007 8
6 天使与魔鬼 2007 6
7 达芬奇 Code 2007 6

在模式“^[abcd]”中,插入符号 (^) 要求匹配从值的开头开始,字符列表 [abcd] 只接受首字母为 a、b、c 或 d 的字符。在默认排序规则下,比较不区分大小写,这就是为什么“Code 返回名称“Black”。

排除字符列表为否定字符的字符

现在让我们修改脚本,对字符列表取反,看看会返回哪些行。

SELECT * FROM `movies`
WHERE `title` REGEXP '^[^abcd]';

在以下位置执行上述脚本 MySQL 使用 Workbench 对 myflixdb 数据库进行测试,得到以下结果。

电影 ID 标题 导向器 发行年份 类别编号
1 加勒比海盗4 罗伯·马歇尔 2011 1
2 忘掉莎拉·马歇尔 尼古拉斯·斯托勒 2008 2
3 X-战警 2008
9 Honey moonERS 约翰舒尔茨 2005 8
16 67% 有罪 2012
17 大独裁者 查理·查普利 1920 7
18 样片 匿名 8
19 电影3 约翰·布朗 1920 8

在字符列表中,插入符号的含义发生了变化:'^[^abcd]' 仍然将匹配项锚定在开头,而 [^abcd] 现在排除所有以所包含字符之一开头的标题。

这两个例子仅使用了锚点和字符列表。下一节将介绍完整的元字符集。

正则表达式元字符

以上示例展示了最简单的正则表达式形式。元字符允许您对模式搜索进行微调:它们可以表示重复、替代、范围和位置。下表列出了所有支持的元字符。 MySQL 正则表达式运算符,并为每个运算符提供一个修正后的示例。

夏亚 描述 例如:
* 星号(*) 匹配零 (0) 个或多个实例 单个字符 在它之前。 SELECT * FROM 电影 WHERE 标题 REGEXP 'da*'; 匹配字母“d”后跟零个或多个字母“a”,例如达芬奇 Code 《爸爸的小女孩》也符合条件。当字母“a”必须出现时,请使用“da+”。
+ 加号(+) 与前面的一个或多个字符匹配。 从 `电影` 中选择 * 其中 `标题` REGEXP'mon+'; 列出所有包含“mon”后跟一个或多个“n”字符的电影。例如,《天使与魔鬼》。
? 问号(?) 匹配零个(0)或一个与其前面的字符。 从 `categories` 中选择 *,其中 `category_name` REGEXP'com?'; 匹配“co”,可选配“m”。例如,喜剧和浪漫喜剧。
. 点 (.) 匹配除换行符以外的任何单个字符。 从电影中选择*其中`year_released` REGEXP'200。'; 列出所有以“200”开头,后跟任意单个字母的年份上映的电影。例如,2005、2007、2008。
[ABC] 角色列表 [abc] 匹配所包含的任意一个字符。 从 `电影` 中选择 * 其中 `标题` REGEXP '[vwxyz]'; 列出所有包含“vwxyz”中任意单个角色的电影。例如,《X战警》和《达芬奇》。 Code.
[^abc] 否定列表 [^abc] 匹配除括号内字符以外的任何字符。 从 `电影` 中选择 * 其中 `标题` REGEXP '^[^vwxyz]'; 列出所有片名不以“vwxyz”中的字符开头的电影。
[AZ] 范围 [AZ] 匹配任何大写字母。 从 `成员` 中选择 * 其中 `邮政地址` REGEXP '[AZ]'; 列出所有邮政地址包含 A 到 Z 之间字母的会员。例如,会员编号为 1 的 Janet Jones。
[az] 范围 [az] 匹配任何小写字母。 从 `成员` 中选择 * 其中 `邮政地址` REGEXP '[az]'; 列出邮政地址中包含字母 a 到 z 的所有成员。请注意,默认排序规则不区分大小写,因此该范围也包含大写字母。
[0-9] 范围 [0-9] 匹配 0 到 9 之间的任意数字。 SELECT * FROM `members` WHERE `contact_number` REGEXP '[0-9]'; 列出所有联系电话中至少包含一位数字的成员。例如,Robert Phil。
^ 插入符号 (^) 将匹配项锚定到值的开头。 从 `电影` 中选择 * 其中 `标题` REGEXP '^[cd]'; 列出所有片名以“c”或“d”开头的电影。例如: Code 给《布莱克》、《爸爸的小女孩》和《达芬奇》起名字 Code.
$ 美元符号 ($) 将匹配项锚定到值的末尾。 SELECT * FROM `movies` WHERE `title` REGEXP 'code$'; 列出所有片名以“code”结尾的电影。例如,《达芬奇》 Code.
| 竖线 (|) 隔离替代方案。 从 `电影` 中选择 * 其中 `标题` REGEXP '^[cd]|^[u]'; 列出所有片名以“c”、“d”或“u”开头的电影。例如: Code 名字:布莱克,达芬奇 Code以及《黑夜传说》—— AwakenING。
\b 单词边界 (\b) 匹配单词的开头或结尾。它取代了旧的 [[:<:]] 和 [[:>:]] 标记,这些标记 MySQL 8.0 已移除。 SELECT * FROM `movies` WHERE `title` REGEXP '\\bfor'; 列出所有以“for”开头的电影。例如,《忘掉莎拉·马歇尔》。 MySQL 5.7 等效模式为'[[:<:]]for'。
[[:班级:]] 字符类 匹配一组指定的字符:[[:alpha:]] 代表字母,[[:space:]] 代表空格,[[:punct:]] 代表标点符号,[[:upper:]] 代表大写字母。注意…… 翻番 方括号。 SELECT * FROM `movies` WHERE `title` REGEXP '^[[:alpha:][:space:]]+$'; 列出所有片名仅包含字母和空格的电影。例如,《忘掉莎拉·马歇尔》(Forgetting Sarah Marshal),而《加勒比海盗4》(Pirates of the Caribean 4)由于片名中包含数字而被排除在外。

反斜杠 (\) 是转义字符。因为 MySQL 首先解析字符串,然后解析模式;字面反斜杠必须写成双反斜杠(\\)在正则表达式模式中。

⚠️ 版本警告: MySQL 8.0.4 版本用 ICU 库替换了旧的正则表达式引擎。该版本移除了词标记 [[:<:]] 和 [[:>:]],因此从旧版本复制的模式会报错,提示“语法错误”。 MySQL 8.0. 请改用 \b。

既然每个元字符都已定义,那么接下来就出现了一个合理的问题:何时应该使用正则表达式 (REGEXP) 来代替更简单的 LIKE 运算符?

正则表达式 (REGEXP) 与 LIKE:你应该使用哪一个?

这两个运算符都按模式过滤行,但它们解决的问题不同。LIKE 运算符仅识别两个符号,而 REGEXP 运算符则识别上面所示的完整元字符集。这种强大的功能是有代价的,因此选择它是一种权衡,而不是一种偏好。

标准 REGEXP
图案符号 % 和 _ 仅 Anchors、范围、交替、量词、字符类
典型用途 前缀、后缀和“包含”搜索 验证、多种替代方案、位置感知匹配
索引使用情况 当图案不以 % 开头时,这种情况可能发生。 从不使用索引
返回值 对或错 返回值为 1 或 0,当任一操作数为 NULL 时,返回值为 NULL。

对于简单的匹配,请选择 LIKE 函数,因为它易于阅读且仍然可以使用索引。当单个模式需要同时表达多个规则时,例如“以 c 或 d 开头并以数字结尾”,请选择 REGEXP 函数。对于大型表,首先使用索引条件缩小行范围,然后将 REGEXP 应用于缩小后的集合。

MySQL 8.0 正则表达式函数

正则表达式运算符只回答一个问题:该值是否与模式匹配? MySQL 8.0 版本新增了四项功能,进一步扩展了定位功能,例如……tract,并重写匹配的文本。每个函数都接受一个可选的 match_type 参数,其中 'c' 强制区分大小写进行比较,'i' 强制不区分大小写进行比较。

  • REGEXP_LIKE(expr, pattern) 当值与模式匹配时返回 1。它是正则表达式运算符的函数形式,`match_type` 参数明确区分大小写。
  • REGEXP_INSTR(expr, pattern) 返回匹配项中第一个字符的位置,如果未找到匹配项,则返回 0。
  • REGEXP_SUBSTR(expr, pattern) 返回匹配的子字符串本身,这对于从较长的文本值中提取年份、代码或数字非常有用。
  • REGEXP_REPLACE(表达式, 模式, 替换) 返回替换所有匹配项后的值,因此它可以清理内部数据。 SQL UPDATE 查询.
SELECT title,
       REGEXP_SUBSTR(title, '[0-9]+') AS number_in_title
FROM `movies`
WHERE REGEXP_LIKE(title, '[0-9]');

上述查询返回所有包含数字的电影标题,以及这些数字本身。 MySQL 5.7 这些功能不可用,因此正则表达式运算符仍然是唯一的选择。

常见问题

默认情况下不区分大小写。正则表达式遵循列的排序规则,而标准排序规则是不区分大小写的。要在列名前添加 BINARY 关键字,或者使用 'c' 匹配类型调用 REGEXP_LIKE,可以强制进行区分大小写的比较。

功能上没有区别。RLIKE 是 REGEXP 的同义词。 MySQL 为了兼容性而保留。实践中更倾向于使用正则表达式 (REGEXP),因为 RLIKE 很容易与不相关的函数混淆。 LIKE运算子 用于通配符。

正则表达式不能使用索引,因此 MySQL 逐行评估模式。首先使用索引条件、日期范围或全文索引减少扫描的行数,然后将正则表达式应用于较小的结果集。

是的。人工智能助手会将纯文本规则转换为正则表达式模式,并解释每个元字符。测试结果如下: MySQL 工作台 与样本行相比,因为一个位置错误的锚点会改变整个结果集。

是的。AI 助手会生成 REGEXP_REPLACE 语句,用于去除标点符号、规范化电话号码或删除多余的空格。首先在 SELECT 语句中运行该模式,确认重写后的值,然后再将其应用到其他语句中。 更新语句.

总结一下这篇文章: