mysql:这些函数你真的会用吗?

不好意思,已经有一个多月没有更新了,这一个多月在外出差。在出差的过程中,与这边同事一起讨论一些业务,实现业务,发现原来MySql有很多函数自己并没有掌握,因此,干脆总结一番,当一个查询手册,以后用到可以直接进行查询。

废话不多说,开干!

准备工作:

我们随意创建一张表,添加数据:

sql 复制代码
create table user_info(
    id int auto_increment not null primary key comment '主键Id',
    user_name varchar(100) not null comment '用户名',
    age smallint not null comment '年龄',
     val varchar(30)
);


insert into user_info (user_name, age) values ('zhangsan',21,'1,2,3,4');
insert into user_info (user_name, age) values ('sili',25);
insert into user_info (user_name, age) values ('xili',32);
insert into user_info (user_name, age) values ('xiiili',26);
insert into user_info (user_name, age) values ('wangwu',31);
insert into user_info (user_name, age) values ('zhaoliu',22);

1、like

提到like,小伙伴们肯定会说这有啥难得,不就是模糊查询嘛,like 加单引号再加双百号,就能实现。

的确,like在我们日常工作中用的太多了,在熟悉不过了,但是我们还是要看下它的一些查询。

注:网上有很多说可以使用:[]查询区间内单个字符拼接查询,或者使用#单个数字的,其实mysql并不支持,like会将其整体作为一个字符串进行模糊查询。

1.1 _任意单个字符

需求: 查询以"ili"结尾的长度为4的用户名的数据

sql 复制代码
select * from user_info ui where ui.user_name like '_ili';

执行结果:

从执行结果可以发现xiiili这个用户名称的用户并没有查询出来,符合需求。

1.2 %多字符模糊匹配

需求: 查询以"zhao"或"zhan"开头的用户名用户信息。

根据需求,我之前的写法直接是两个like进行查询:

sql 复制代码
select * from user_info ui where (ui.user_name like 'zhao%' or ui.user_name like 'zhan%');

2、regexp

说实话这个函数我基本没有用过,不过在搜寻mysql为啥不支持like中使用[]时发现的,因此记录一下。

regexp:支持正则表达式进行字段查询。

选项 说明 示例
^ 匹配文本的开始字符 ^6:表示查询以6开头的数据
$ 文本的结束字符 6$:表示查询以6结尾的数据
. 匹配任意单个字符 '李.':表示以李开头的,长度为2的数据
* 零个或多个字符 '李*':表示以李开头的或是李数据
+ 前面的字符出现1次或多次 '李四+':表示以李开头的,并包含四的数据
<字符串> 包含字符串的数据 即跟like '%%'一样的效果
[字符串] 匹配字符集合任何一个字符 [09]:即0和9任意一个数字。[0-9]:即0到9之间任意一个数字
[^] 不匹配集合中任何一个字符 即[]的非
字符串{n} 字符串至少出现n次 'g{2}':表示查询字段中至少包含2个或2个以上g的数据
字符串{n,m} 前面的字符串至少出现n次,至多出现m次 'g{2,4}':表示查询字段中至少包含2个g,至多包含4个g的数据

需求: 查询以"zhao"或"zhan"开头的用户名用户信息。

sql 复制代码
SELECT * FROM user_info WHERE user_name regexp '^zhao|^zhan';

执行结果:

3、locate/find_in_set

locate与find_in_set都是查询字符或字符串在其他字符串中第一次出现的位置。

locate(n,m) :即n在m中第一次出现的位置,不包含时返回0。locate会将m作为一整个字符来进行匹配,不会因为存在逗号","而算成多个字符。

find_in_set(n,'m,n,l') :可以理解为n在一个集合中第一次出现的位置,多个字符匹配需要用逗号进行拼接且分隔的字符必须与n相等。

需求:查询用户名称中存在zhao的用户信息。

sql 复制代码
-- locate查询
select * from user_info ui where locate('zhao',ui.user_name) > 0;

--find_in_set查询
select * from user_info ui where find_in_set('zhao',ui.user_name) > 0;

执行结果:

  1. locate执行结果:
  1. find_in_set查询:

由查询结果我们可以看到locate实现了模糊匹配,而find_in_set查询是进行全匹配的,即与mysql中的=一样。

4、json_object

有时候我们希望一些字段以json的格式返回,此时可以使用json_object。

json_object:将查询的数据以json的格式输出。

json_object(key,value[,key,value......]) :key与value必填。

需求: 将用户名以"zhao"开头的用户信息,以json格式输出。

sql 复制代码
select json_object('userName',user_name,'age',age) jsonData from user_info ui where locate('zhao',ui.user_name) > 0;

执行结果:

4.1 json操作

在很多数据库中一个字段可能会保存json格式的数据,我们也会对这些数据进行筛选等操作。那么我们来看下json数据怎么进行操作呢?

4.1.1 条件精确查找

格式:json字符 -> '$.字段名'=数值 json_contains(json数据,'查询值','查询json字段')

注:使用json_contains查询字符串匹配时,需加上""双引号,这是因为json数据中字符串是用双引号引用

例如,我们在上述生成的json中获取年龄为22的数据。

sql 复制代码
select *
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui
         where locate('zhao', ui.user_name) > 0) sel
where sel.jsonData -> '$.age' = 22;

-- 或

select *
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui
         where locate('zhao', ui.user_name) > 0) sel
where json_contains(sel.jsonData,'"zhaoliu"','$.userName');

执行结果:

4.1.2 获取json属性值

我们可能会获取json中的某些数据的对应值展示到前端,这时候我们需要用到:json_extract

格式:json_extract(json数据,$.json字段名)

例如:我们在上述生成的json中获取字段年龄的数据。

sql 复制代码
select json_extract(sel.jsonData,'$.age') age
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui
         where locate('zhao', ui.user_name) > 0) sel

执行结果:

4.1.3 条件模糊查找

对json数据模糊查询可以使用:json_extract获取字段值后结合like查询。

格式:json_extract(json数据,$.json字段名) like '%查询字符%' json字符 -> '$.字段名' like '%查询字符%'

例如:在上述生成的json数据中查询用户名包含zhao的数据。

sql 复制代码
select *
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui) sel
where json_extract(sel.jsonData,'$.userName') like '%zhao%';

-- 或
select *
from (
         select json_object('userName', user_name, 'age', age) jsonData
         from user_info ui) sel
where sel.jsonData -> '$.userName' like '%zhao%';

执行结果:

当然mysql对于json的操作还提供了其他一些方法,有兴趣的小伙伴可以去官网看看,在此我就不一一介绍了。

5、substring_index

substring_index顾名思义就是通过索引来截取字符串。

应用:在字符串中可以根据某些字符的位置进行截取

substring_index('待截取字符串','截取字符','截取字符位置N')

当截取字符位置N为-1时表示截取从字符的最后出现的位置开始截取。相当于java中substring(str.lastIndexOf(",");

例如:定义一个字段:a,b,c,要截取第二个逗号前的字符

sql 复制代码
select SUBSTRING_INDEX('a,b,c', ',',2)

结果:

5.1 行转列

在很多时候一列中数据可能会将多个值用逗号分隔而保存。也会因为业务要求要将逗号分隔的数据换成一列列数据进行统计。例如:一列数据为:1,2,3 需要转换成1为一行,2为1行,3为一行三行数据。

sql 复制代码
select substring_index(substring_index(uio.val, ',', xg.ID), ',', -1) vals
from user_info uio
         join xmjg_gmjjhylb xg on xg.ID <= (length(uio.val) - length(replace(uio.val, ',', '')) + 1)
where user_name = 'zhangsan';

执行结果:

在行转列中用到了两个substring_index,其中:

substring_index(uio.val, ',', xg.ID) :会根据每一次循环的Id值不同,而获取到不同的字符。注:id必须要从1开始。

substring_index(substring_index(uio.val, ',', xg.ID), ',', -1) :根据获取的不同字符,获取逗号后面的一个值。

上述这些函数就是在我这一个多月出差中,会用到的,希望对大家有所启发。 期待小伙伴们也能够通过一些函数的用法,大家相互学习,共同进步。

相关推荐
QX_hao1 小时前
【Go】--map和struct数据类型
开发语言·后端·golang
MC丶科1 小时前
【SpringBoot 快速上手实战系列】5 分钟用 Spring Boot 搭建一个用户管理系统(含前后端分离)!新手也能一次跑通!
java·vue.js·spring boot·后端
G探险者2 小时前
为何一个系统上线要经过N轮测试?带你看懂企业级发布体系
后端
TDengine (老段)3 小时前
TDengine 数学函数 DEGRESS 用户手册
大数据·数据库·sql·物联网·时序数据库·iot·tdengine
TDengine (老段)3 小时前
TDengine 数学函数 GREATEST 用户手册
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
@yanyu6663 小时前
idea中配置tomcat
java·mysql·tomcat
安当加密3 小时前
云原生时代的数据库字段加密:在微服务与 Kubernetes 中实现合规与敏捷的统一
数据库·微服务·云原生
lang201509283 小时前
Spring Boot 入门:5分钟搭建Hello World
java·spring boot·后端
爱喝白开水a3 小时前
LangChain 基础系列之 Prompt 工程详解:从设计原理到实战模板_langchain prompt
开发语言·数据库·人工智能·python·langchain·prompt·知识图谱