MySQL模糊查询/模式匹配(Pattern Match)

      使用SQL查询数据时,时常会遇到这种情况,我们并不需要精确的匹配,而是要查找具有某类特点的数据。这种场景我们就要用到模糊查询。MySQL中常用的模糊查询方法有2种:

  • like语句模糊查询
  • regexp正则表达式模式匹配

目录

一、使用like模糊匹配

二、使用正则表达式模式匹配

2.1 普通匹配

2.2 位置匹配

2.3 特定次数匹配

2.4 特定模式匹配

2.5 修改匹配的数据


、使用like模糊匹配

当只需要进行简单模糊查询时,可以利用like语句完成,like可以用来模糊匹配字符串。

like语句的语法是:expr [not] like 'pattern'。expr可以是我们的数据列或者某种表达式,pattern就是我们想要查询的数据具有的模式。在'pattern'中,可以使用'_'来匹配单个字符或'%'来匹配任意字符串(包含空字符,但不会匹配null)。

下面用一个示例来演示like用法,先建立一张测试表:

create table test(
id int not null primary key,
value varchar(32));

insert into test values(1,'abc'),(2,'abcd'),(3,'abc123'),(4,'ab123xyz');

查询和abc有关的数据:

select * from test;

select * from test where value like 'abc';

  • 当模式中没有_或%时,like会只用精确匹配(相当于=),这里只有abc了被匹配出来。

使用_匹配单个字符(包含空字符,但不会匹配null):

select * from test where value like 'abc_';

这里的模式是'abc_',使用_匹配单个字符,只有abcd被匹配了出来。

使用%匹配任意字符:

select * from test where value like 'abc%';

当使用%,匹配包含空字符在内的所有字符串。

使用not like反向匹配,即所有符合模式的都不查询出来:

select * from test where value not like 'abc%';

这里所有以abc开头的字符串都不会显示出来。

上面的例子都是以查找以abc开头的示例,_和%可以出现在模式的任何地方。需要注意的一点是,如果匹配的字段上有索引,如果遇到'%str'这种将%放在模式开头,那么将会导致索引失效,使用中需要斟酌一下性能。

二、使用正则表达式模式匹配

like 匹配的方式可以完成一些简单的模糊查询,例如你可以用%abc%来匹配任意包含abc的数据,但是如果问题换成:包含a或b或c,那么你就要写3次匹配,如果问题更复杂一点(例如匹配特定次数),like可能就无法完成了,此时你就需要采用正则表达式匹配。

正则表达式是一个包含文本和特殊字符的字符串,利用它可以识别各种复杂模式的字符串。MySQL可以通过regexp或rlike(这两个是同义词)操作符来完成正则表达式的匹配,语法和like一样 expr [not] regexp 'pattern'。

正则表达式的匹配结果,如果成功则返回1,失败返回0,用在where条件中分别对应真/假:

select 'abcd' regexp 'abc';

select 'abcd' regexp '123';

下面演示几类最常用的正则表示式匹配场景,我们先将测试数据换成更复杂内容:

truncate table test;

insert into test values(1,'abc'),(2,'abcd'),(3,'abc 1'),(4,'abc1,xkz'),(5,'abc13'),(6,'xyzABC123'),(7,'xyzabc1223'),(8,'123456'),(9,'1212123xyzabc');

commit;

测试数据如下:

select * from test;

2.1 普通匹配

普通匹配和like类似,直接输入字符串,则会匹配出包含改字符串的值:

select * from test where value regexp 'abc';

  • regexp 'abc' 相当于like '%abc%',所有包含abc的都匹配的出来,除了id为8的纯数字。

反向匹配,可以直接在regexp 前加上not,或者整体取反:

select * from test where value not regexp 'abc';

select * from test where not(value regexp 'abc');

  • expr not regexp … 和 not (epxr regexp …)两种写法是等效的

2.2 位置匹配

某些时候我们需要从特定的位置开始匹配,正则表达式可以通过^和$来指定匹配的位置:

  • ^ 代表从开头进行匹配
  • $ 代表从结尾进行匹配

匹配以'xyz'开头的数据

select * from test where value regexp '^xyz';

匹配以'23'结尾的数据

  • (23)的小括号表示这是一个整体

2.3 特定次数匹配

有些时候我们想知道某种模式出现的次数,这时我们就需要用到次数匹配了,常用的次数匹配模式如下:

  • […]   匹配方括号出现的任意字符
  • .       匹配任意单个字符
  • *      匹配前面模式0次或多次
  • +     匹配前面模式1次或多次
  • ?    匹配前面模式0次或1次
  • {m}  匹配前面模式m次
  • {m,n} 匹配前面模式m到n次

匹配包含字符串'k'或者'5'的数据:

select * from test where value regexp '[k5]';

匹配x和z中间包含一个字符的模式:

select * from test where value regexp 'x.z';

匹配以abc开头,后面跟任意字符

select * from test where value regexp '^abc.*';

  • .* 代表任意字符出现任意次数,可以匹配任何字符,这里去掉效果也是一样的

匹配abc1之后,出现1次或多次2的数据:

  1. select * from test where value regexp 'abc12+';

  • abc12+,+代表前面的2出现1次或多次

匹配abc1之后,出现0次或1次2的数据:

select * from test where value regexp 'abc12?';

  • 注意和上个例子区别,?代表0次或1次,因此只要含abc1就会匹配出来
  • id为7的数据,结尾1223,满足了出现1次2,所以也被查了出来

查询abc1之后,2出现2次的数据:

select * from test where value regexp 'abc12{2}';

  • 只要2出现2次即视为满足条件,如果出现更多次数的2,依然是满足的(并不管后续数据,只要匹配到2次就判定成功)。

查询包含6个数据的数据:

select * from test where value regexp '[0-9]{6}';

  • [0-9]代表数字1到9任意数字,{6}代表重复6次,只要有6个连续的数字即满足条件。

查询仅包含6个数字的数据:

select * from test where value regexp '^[0-9]{6}$';

  • 我们把上个模式用^和$限制起来,代表从开头到结尾,只有6数字,id为9的数据(数字后包含字符串)就不匹配了。

查询'12'重复1到2次的数据:

select * from test where value regexp 'abc(12){1,2}';

  • (12)用括号括起来代表一个整体
  • {1,2} 代表匹配1次或2次,只要满足即可以。

2.4 特定模式匹配

MySQL还提供了一些特殊字符串来表示某一类字符,其格式是[:character_class:],常用的类别有:

  • [:digit:] 表示所有数字
  • [:alpha:] 表示所有字符
  • [:alnum:] 表示所有数字和字符
  • [:blank:] 表示空白字符
  • [:punct:] 表示标点符号
  • [:upper:] 表示大写字符
  • [:lower:] 表示小写字符

查询所有以数字开头的记录:

select * from test where value regexp '^[:digit:]';

  • [:digit:] 代表所有数字,前面的^代表从开头开始匹配

查询所有以字母结尾的记录:

select * from test where value regexp '[:alpha:]$';

查询所有包含数字或字母的记录:

select * from test where value regexp '[:alnum:]';

查询所有包含空格的记录:

select * from test where value regexp '[:blank:]';

查询所有包含标点符号的记录:

select * from test where value regexp '[:punct:]';

查询包含大写字母的记录:

select * from test where value regexp '[:upper:]' COLLATE utf8mb4_0900_as_cs;

  • 这里多了一个子句COLLATE utf8mb4_0900_as_cs,指定排序规则区分大小写。MySQL8.0中字符集utf8mb4的默认排序规则是utf8mb4_0900_ai_ci,它是不区分大小写的(排序规则结尾的ci代表Case Insensitive 大小写不敏感,cs代表Case Sensitive 大小写敏感)。

如果不加这个排序规则子句,默认是不区分大小写的,纯小写字符记录也会被查询出来,与我们想查大写字符的意愿不同:

select * from test where value regexp '[:upper:]';

你也可以使用函数regexp_like函数中的参数来指定大小写是否敏感(这个函数是regexp的另一种写法):

select * from test where regexp_like(value, '[:upper:]', 'c')=1;

  • 前两个参数是expr和pattern,第三个参数可以指定大小写是否敏感:'c' 大小写敏感,'i' 大小写不敏感

2.5 修改匹配的数据

很多时候,我们查找出某类数据后,就是为了修改它,利用regexp_replace函数可以修改正则表达式的匹配结果。

语法:regexp_replace(expr, pattern, replacement [, pos[, occurrence[, match_type]]])

参数解释:

  • expr: 要搜索的内容
  • pattern: 匹配的模式
  • replacement: 替换的内容
  • pos: 起始搜索的位置,默认是1,即从头开始匹配
  • occurrence: 匹配发生的次数,默认是0,即替换所有匹配项
  • match_type: 匹配模式,和regexp_like相同,常用的是:'c' 大小写敏感,'i' 大小写不敏感

下面通过几个示例来理解,将字符串'ababab'中的a替换为x:

select regexp_replace('ababab','a','x');

将字符串'ababab'中的a替换为x,但是从第2位开始搜索:

select regexp_replace('ababab','a','x',2);

  • 这里使用了一个位置参数2,表示从第二位开始搜索,所以开头的a没有被替换

将字符串'ababab'中的a替换为x,但是从第2位开始搜索,并将第2次匹配的位置替换为x:

select regexp_replace('abababab','a','x',2,2);

  • 这里使用了位置参数2,和发生的次数2,即从第2位开始,只有第二个匹配的a会被替换为x

将test表中的首次匹配2大写字符替换为字符串'这里有两个大写字符':

select value, regexp_replace(value,'[:upper:]{2}','这里有两个大写字符',1,1,'c') after_replace from test where value regexp '[:upper:]' COLLATE utf8mb4_0900_as_cs;

  • 模式[:upper:]{2},代表任意大写字符重复2次
  • 后面的1,1分别代表从头开始搜索,只匹配第一次
  • 'c' 代表大小写敏感

修改前要先查询一下元数据和修改后的数据(最好备份一下),一是确认修改范围是不是我们想要匹配的数据,二是修改结果对不对,没有问题时再执行update:

update test set value=regexp_replace(value,'[:upper:]{2}','这里有两个大写字符',1,1,'c') where value regexp '[:upper:]' COLLATE utf8mb4_0900_as_cs;

select * from test;

可以看到,我们通过正则表达式匹配并更新成功了。

注意:在MySQL8.0.17版本前,这个函数返回的结果字符集是UTF-16(这是一个BUG),这可能导致你查询的结果和最后的更新结果不同,因此采用此函数批量匹配更新前一定要做好备份。

以上便是MySQL中常用的模糊匹配方法,可以满足大部分场景的模糊匹配。但是如果数据量非常大,例如需要在富文本中匹配想要的数据,上面的匹配方法有可能会比较慢,此时可以考虑采用使用另一种匹配技术:全文索引(Full-Text Index)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/127227.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大厂面试题-为什么索引要用B+树来实现呢,而不是B树?

首先,常规的数据库存储引擎,一般都是采用B树或者B树来实现索引的存储。 (如图)因为B树是一种多路平衡树,用这种存储结构来存储大量数据,它的整个高度会相比二叉树来说,会矮很多。 而对于数据库来说,所有的…

【191】Java8在大比例尺小范围地图上,根据wgs84坐标系的经纬度计算两个点之间的方向和距离

场景 本文代码在大比例迟、小范围的地图上测试过。这些地图一般是县、区、镇、街道等范围的,其测试效果较好。由于地图范围较小,可以把经纬度近似看作直线。 问题分析 方向一共分东、南、西、北、东北、西北、西南、东南共八个方向。一周是 360 度&am…

最新GitHub学生认证,可以愉快的使用Copilot了(保姆级教程)

🎈博客主页:🌈我的主页🌈 🎈欢迎点赞 👍 收藏 🌟留言 📝 欢迎讨论!👏 🎈本文由 【泠青沼~】 原创,首发于 CSDN🚩&#x1f…

“深入理解机器学习性能评估指标:TP、TN、FP、FN、精确率、召回率、准确率、F1-score和mAP”

目录 引言 分类标准 示例:癌症检测 1. 精确率(Precision) 2. 召回率(Recall) 3. 准确率(Accuracy) 4. F1-score 5. mAP(均值平均精度) 总结与通俗解释 引言 机器…

电销行业获客的精准客源从哪里来的?

在电话营销行业中找到精确的客户资源对电话营销的成功至关重要。 这里有几种方法可以找到准确的客户资源: 1、自身数据库:首先,使用现有的客户信息数据库,如客户电话号码、电子邮件和地址,来推广和营销现有客户。 2…

django 批量 serializers listserializers

Django drf 序列化器 序列化器 扩展serializers的有用性是我们想要解决的问题。但是,这不是一个微不足道的问题,而是需要一些严肃的设计工作。— Russell Keith-Magee, Django用户组 序列化器允许把像查询集和模型实例这样的复杂数据转换为可以轻松渲染…

基于element-plus定义表单配置化

文章目录 前言一、配置化的前提二、配置的相关组件1、新建form.vue组件2、新建input.vue组件3、新建select.vue组件4、新建v-html.vue组件5、新建upload.vue组件6、新建switch.vue组件7、新建radio.vue组件8、新建checkbox.vue组件9、新建date.vue组件10、新建time-picker.vue组…

泄露35TB数据,医疗巨头Henry Schein遭受黑猫勒索组织攻击

近日,据Bleeping Computer 网站消息,BlackCat(黑猫)勒索软件团伙将医疗保健巨头Henry Schein 添加到了其暗网泄露网站,并声称其破坏了该公司的网络,窃取了35 TB的敏感文件,这些文件包括了Henry …

【算法】道路与航线(保姆级题解)

题目 农夫约翰正在一个新的销售区域对他的牛奶销售方案进行调查。 他想把牛奶送到 T 个城镇,编号为 1∼T。 (存在T个点) 这些城镇之间通过 R 条道路 (编号为 1 到 R) 和 P 条航线 (编号为 1 到 P) 连接。 (存在R条道路&#…

Bytebase 2.11.0 - 支持 OceanBase Oracle 模式

🚀 新功能 支持 OceanBase Oracle 模式。支持设置 MySQL 在线变更参数。新增项目数据库查看者的角色。 🎄 改进 支持在项目中直接选择所有用户并为之添加角色。 调整了项目页面的布局。在 SQL 编辑器中通过悬浮面板展示表和列的详情。 🪦 …

全局后置路由守卫(afterEach)

全局后置路由守卫(afterEach) 功能:每一次切换任意路由组件之后都会被调用,相当于在进入下一个路由组件之后设置一个权限。 使用原理 代码创建的位置: 在创建router之后(const router new VueRouter&…

基于自然语言处理的结构化数据库问答机器人系统

温馨提示:文末有 CSDN 平台官方提供的学长 Wechat / QQ 名片 :) 1. 项目简介 知识库,就是人们总结出的一些历史知识的集合,存储、索引以后,可以被方便的检索出来供后人查询/学习。QnA Maker是用于建立知识库的工具,使用…

JAVA IDEA 下载

超简单步骤一: IntelliJ IDEA 官方下载链接 点击以上链接进入下图,点击下载 继续点下载,然后等待下载完后打开安装包即可 步骤二: 打开下好的安装包,点击Browse...我们把它下载到自己喜欢的地方(主要是别占…

Java类和对象详解

文章目录 面向对象概述类和对象类定义和使用定义使用 对象引用对象的初始化和构造构造方法默认初始化就地初始化 面向对象概述 面向对象是一种现在主流的程序设计方法,现如今的大部分语言都支持面向对象,Java的面向对象是由C的面向对象衍生而来&#xf…

Talk | 马里兰大学博士生吴曦旸:分布式多智能体强化学习在复杂交通轨迹规划中的应用

本期为TechBeat人工智能社区第545期线上Talk! 北京时间11月09日(周四)20:00,马里兰大学博士生—吴曦旸的Talk已准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “分布式多智能体强化学习在复杂交通轨迹规划中的应用”,介…

SpringBoot定时任务打成jar 引入到新的项目中后并自动执行

一、springBoot开发定时任务 ①&#xff1a;连接数据库实现新增功能 1. 引入依赖 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional> </dependency> <dependen…

阿里云竞争加剧,腾讯云双十一服务器优惠力度爆表!

腾讯云对于新客户和老客户都有相互照顾的优惠力度。特别是在今年的双十一活动中&#xff0c;腾讯云推出了一系列的优惠活动。首先&#xff0c;轻量服务器和云服务器产品的首购活动中&#xff0c;三年的云服务器仅需540元&#xff0c;这是一个非常低廉的价格。其次&#xff0c;香…

2.3.4 交换机的DHCP技术

实验2.3.4 交换机的DHCP技术 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施1.交换机的基本配置。2.将交换机的接口配置为trunk模式&#xff0c;并允许vlan10 和vlan20通过。3.开启交换机的DHCP功能。4.配置交换机的DHCP服务。5.配置vlan的vlanif接口的IP地址&…

【Spring】事务实现原理

在使用事务的时候需要添加EnableTransactionManagement注解来开启事务&#xff0c;Spring事务底层是通过AOP来实现的&#xff0c;所以启用事务后&#xff0c;同样会向容器中注入一个代理对象创建器&#xff0c;AOP使用的是AnnotationAwareAspectJAutoProxyCreator&#xff0c;事…

易点易动固定资产管理系统:实现财务与OA系统的无缝对接,高效管理固定资产

在现代企业经营中&#xff0c;固定资产管理是一个非常重要的环节。准确记录和管理固定资产不仅对企业的财务状况有直接影响&#xff0c;还能提高资产利用率、降低运营成本&#xff0c;并确保企业的合规性。然而&#xff0c;传统的固定资产管理方式往往存在繁琐、效率低下的问题…