MySQL提取JSON字段数据实现查询


Posted in MySQL onApril 22, 2022

前言

昨天上线后通过系统报警发现了一个bug,于是紧急进行了回滚操作,但是期间有用户下单,数据产生了影响,因此需要排查影响了哪些订单,并对数据进行修复。

1. 问题现象

由于bug导致了订单表的customer_extra_info字段的hasFreightInsurance误更新成了“是”,因此需要查询回滚前一共有多少被误更新为“是”的订单,如下图:

MySQL提取JSON字段数据实现查询

于是查看订单表中customer_extra_info字段类型发现是JSON类型的

MySQL提取JSON字段数据实现查询

2. 解决方案

查询资料发现mysql5.7以后提供了一种新的字段格式-json。

对JSON类型的数据MySQL提供了相关的查询操作。

先给出查询SQL,后面在介绍MySQL对JSON类型字段的查询操作

SELECT
	* 
FROM
	( SELECT id, customer_extra_info -> '$.hasFreightInsurance' AS Insurance FROM oms_order_list WHERE project_id = 1 AND update_time > '2022-04-15 16:30:17' ) t 
WHERE
	JSON_CONTAINS ( Insurance, JSON_OBJECT ( "value", "是" ) )

3. JSON数据查询

3.1 一般基础查询操作

1、使用 json字段名->’$.json属性’ 进行查询条件

SELECT
	id,
	customer_extra_info
FROM
	oms_order_list 
WHERE
	project_id = 1 
	AND update_time > '2022-04-15 16:30:17'
	AND customer_extra_info -> '$.maxClaimAmount'=10

查询结果如下:

MySQL提取JSON字段数据实现查询

 2、关联表查询

json字段也支持关联表的查询,这里只写出使用方法,不做实例展示。其中deptLeaderId和id分别是dept,dept_leader两个表中的关联字段。

SELECT * from dept,dept_leader WHERE dept.json_value->'$.deptLeaderId'=dept_leader.json_value->'$.id' ;

3.2 一般函数查询操作

写到这里大家都发现了,我们查询的json都是整条json数据,这样看起来不是很方便,那么如果我们只想看json中的某个字段怎么办?

这样就引入了我们的第一个函数:json_extract(字段名,json字段名)

在详细介绍用法之前我们可以看看官网的函数介绍:

MySQL提取JSON字段数据实现查询

 咱们可以看到官网介绍json_extract()这个函数很详细:Return data from JSON document

从json中返回字段

1、函数 json_extract():从json中返回想要的字段

用法:json_extract(字段名,$.json字段名)
实例:

SELECT
	id,
	json_extract ( customer_extra_info, '$.hasFreightInsurance' ) AS hasFreightInsurance 
FROM
	oms_order_list 
WHERE
	project_id = 1 
	AND update_time > '2022-04-15 16:30:17'

查询结果如下:

MySQL提取JSON字段数据实现查询

2、函数JSON_CONTAINS():JSON格式数据是否在字段中包含特定对象 

用法: JSON_CONTAINS(target, candidate[, path])
实例:

SELECT
	id,
	customer_extra_info 
FROM
	oms_order_list 
WHERE
	project_id = 1 
	AND update_time > '2022-04-15 16:30:17' 
	AND JSON_CONTAINS ( customer_extra_info, JSON_OBJECT ( "maxClaimAmount", 10 ) )

查询结果如下:

MySQL提取JSON字段数据实现查询

3、函数JSON_OBJECT():将一个键值对列表转换成json对象 

比如我们想查询某个对象里面的值等于多少

我们可以看到hasFreightInsurance中还有一个对象,里面还有name和value两个属性字段,那么我们应该怎么查询value=否的订单呢。

用法:JSON_OBJECT([key, val[, key, val] …])
实例:

SELECT
	* 
FROM
	( SELECT id, customer_extra_info -> '$.hasFreightInsurance' AS Insurance FROM oms_order_list WHERE project_id = 1 AND update_time > '2022-04-15 16:30:17' ) t 
WHERE
	JSON_CONTAINS ( Insurance, JSON_OBJECT ( "value", "否" ) )

查询结果如下:

MySQL提取JSON字段数据实现查询

4、函数JSON_ARRAY():创建JSON数组

​用法:JSON_ARRAY([val[, val] …])

实例:我们要查询deptName包含1的数据

SELECT
	id,
	customer_extra_info 
FROM
	oms_order_list 
WHERE
	project_id = 1 
	AND update_time > '2022-04-15 16:30:17' 
	AND JSON_CONTAINS ( customer_extra_info -> '$.deptName', JSON_ARRAY ( "1" ) )

查询结果如下:

MySQL提取JSON字段数据实现查询

5、函数JSON_TYPE():查询某个json字段属性类型

用法:JSON_TYPE(json_val)
事例:比如我们想查询deptName的字段属性是什么

SELECT
	id,
	customer_extra_info -> '$.deptName',
	JSON_TYPE ( customer_extra_info -> '$.deptName' ),
	customer_extra_info -> '$.hasFreightInsurance',
	JSON_TYPE ( customer_extra_info -> '$.hasFreightInsurance' ) 
FROM
	oms_order_list 
WHERE
	project_id = 1 
	AND update_time > '2022-04-15 16:30:17'

查询结果如下:

MySQL提取JSON字段数据实现查询

6、函数JSON_EXTRACT() :从JSON文档返回数据 

这也是我们开发中会经常用到的一个函数

SELECT
	* 
FROM
	oms_order_list 
WHERE
	project_id = 1 
	AND update_time > '2022-04-15 16:30:17' 
	AND JSON_CONTAINS ( JSON_EXTRACT ( customer_extra_info, '$.hasFreightInsurance' ), JSON_OBJECT ( "value", "否" ) )

 查询结果如下:

MySQL提取JSON字段数据实现查询

7、函数JSON_KEYS() :JSON文档中的键数组

 用法:JSON_KEYS(json_value)

实例:比如我们想查询json格式数据中的所有key

SELECT
	id,
	JSON_KEYS ( customer_extra_info ) 
FROM
	oms_order_list 
WHERE
	project_id = 1 
	AND update_time > '2022-04-15 16:30:17'

 查询结果如下:

MySQL提取JSON字段数据实现查询

4. JSON数据新增更新删除

接下来的3种函数都是新增数据类型的:
JSON_SET(json_doc, path, val[, path, val] …)
JSON_INSERT(json_doc, path, val[, path, val] …)
JSON_REPLACE(json_doc, path, val[, path, val] …)

1、函数JSON_SET() :将数据插入JSON格式中,有key则替换,无key则新增
这也是我们开发过程中经常会用到的一个函数

用法:JSON_SET(json_doc, path, val[, path, val] …)

实例:比如我们想针对id=2的数据新增一组:newData:新增的数据,修改deptName为新增的部门1
sql语句如下:

update dept set json_value=JSON_SET('{"deptName": "部门2", "deptId": "2", "deptLeaderId": "4"}','$.deptName','新增的部门1','$.newData','新增的数据') WHERE id=2;
 
select * from dept WHERE id =2

结果:

MySQL提取JSON字段数据实现查询

注意:json_doc如果不带这个单元格之前的值,之前的值是会被新值覆盖的,比如我们如果更新的语句换成:

update dept set json_value=JSON_SET('{"a":"1","b":"2"}','$.deptName','新增的部门1','$.newData','新增的数据') WHERE id=2

我们可以看到这里json_doc是{“a”:“1”,“b”:“2”},这样的话会把之前的单元格值覆盖后再新增/覆盖这个单元格字段

结果:

MySQL提取JSON字段数据实现查询

2、函数JSON_INSERT():插入值(往json中插入新值,但不替换已经存在的旧值)
用法:JSON_INSERT(json_doc, path, val[, path, val] …)

 实例:

UPDATE dept set json_value=JSON_INSERT('{"a": "1", "b": "2"}', '$.deptName', '新增的部门2','$.newData2','新增的数据2') 
WHERE id=2

结果:

MySQL提取JSON字段数据实现查询

 我们可以看到由于json_doc变化将之前的值覆盖了,新增了deptName和newData2.
如果我们再执行以下刚才的那个sql,只是换了value,我们会看到里面的key值不会发生变化。
因为这个函数只负责往json中插入新值,但不替换已经存在的旧值。

3、函数JSON_REPLACE()
用法:JSON_REPLACE(json_doc, path, val[, path, val] …)

用例:
如果我们要更新id=2数据中newData2的值为:更新的数据2

sql语句如下:

UPDATE dept set json_value=JSON_REPLACE('{"a": "1", "b": "2", "deptName": "新增的部门2", "newData2": "新增的数据2"}', '$.newData2', '更新的数据2') WHERE id =2;
 
select * from dept WHERE id =2

结果:

MySQL提取JSON字段数据实现查询

4、函数JSON_REMOVE() :从JSON文档中删除数据
用法:JSON_REMOVE(json_doc, path[, path] …)

举例:删除key为a的字段。

UPDATE dept set json_value=JSON_REMOVE('{"a": "1", "b": "2", "deptName": "新增的部门2", "newData2": "更新的数据2"}','$.a') WHERE id =2;

结果:

MySQL提取JSON字段数据实现查询

5、函数JSON_SEARCH() :用于在json格式中查询并返回符合条件的节点
这是一个非常强大的函数

到此这篇关于MySQL对JSON类型字段数据进行提取和查询的实现的文章就介绍到这了!


Tags in this post...

MySQL 相关文章推荐
一看就懂的MySQL的聚簇索引及聚簇索引是如何长高的
May 25 MySQL
虚拟机linux端mysql数据库无法远程访问的解决办法
May 26 MySQL
MySQL 不等于的三种使用及区别
Jun 03 MySQL
为什么MySQL选择Repeatable Read作为默认隔离级别
Jul 26 MySQL
MYSQL 的10大经典优化案例场景实战
Sep 14 MySQL
mysql数据插入覆盖和时间戳的问题及解决
Mar 25 MySQL
Nebula Graph解决风控业务实践
Mar 31 MySQL
排查MySQL生产环境索引没有效果
Apr 11 MySQL
MySQL库表太大怎么办? 数据库分库分表项目实践
Apr 11 MySQL
MySQL创建管理子分区
Apr 13 MySQL
MySQL提取JSON字段数据实现查询
Apr 22 MySQL
mysql 排序失效
May 20 MySQL
mysql使用FIND_IN_SET和group_concat两个方法查询上下级机构
Apr 20 #MySQL
在MySQL中你成功的避开了所有索引
Apr 20 #MySQL
mysql中如何用命令创建联合唯一索引
Apr 20 #MySQL
mysql 8.0.27 绿色解压版安装教程及配置方法
MySQL去除密码登录告警的方法
Apr 20 #MySQL
MySQL数据库事务的四大特性
Windows 64位 安装 mysql 8.0.28 图文教程
You might like
用Zend Encode编写开发PHP程序
2006/10/09 PHP
php eval函数用法总结
2012/10/31 PHP
PHP数字前补0的自带函数sprintf 和number_format的用法(详解)
2017/02/06 PHP
PHP实现动态压缩js与css文件的方法
2018/05/02 PHP
使用laravel的Eloquent模型如何获取数据库的指定列
2019/10/17 PHP
javascript 添加和移除函数的通用方法
2009/10/20 Javascript
ExtJs之带图片的下拉列表框插件
2010/03/04 Javascript
javascript之bind使用介绍
2011/10/09 Javascript
仿当当网淘宝网等主流电子商务网站商品分类导航菜单
2013/09/25 Javascript
js获取下拉列表框中的value和text的值示例代码
2014/01/11 Javascript
Prototype框架详解
2015/11/25 Javascript
jQuery简单实现iframe的高度根据页面内容自适应的方法
2016/08/01 Javascript
JavaScript中 DOM操作方法小结
2017/04/25 Javascript
Iscrool下拉刷新功能实现方法(推荐)
2017/06/26 Javascript
vue弹窗消息组件的使用方法
2020/09/24 Javascript
详解使用Next.js构建服务端渲染应用
2018/07/10 Javascript
js实现web调用摄像头 js截取视频画面
2019/04/21 Javascript
VUE 实现复制内容到剪贴板的两种方法
2019/04/24 Javascript
echarts大屏字体自适应的方法步骤
2019/07/12 Javascript
vue 接口请求地址前缀本地开发和线上开发设置方式
2020/08/13 Javascript
[01:23]2014DOTA2国际邀请赛 球迷无处不在Ti现场世界杯受关注
2014/07/10 DOTA
[49:15]DOTA2-DPC中国联赛 正赛 CDEC vs XG BO3 第二场 1月19日
2021/03/11 DOTA
编程语言Python的发展史
2014/09/26 Python
利用numpy和pandas处理csv文件中的时间方法
2018/04/19 Python
Python列表list排列组合操作示例
2018/12/18 Python
实例介绍Python中整型
2019/02/11 Python
75条笑死人的知乎神回复,用60行代码就爬完了
2019/05/06 Python
Python求均值,方差,标准差的实例
2019/06/29 Python
OpenCV+face++实现实时人脸识别解锁功能
2019/08/28 Python
Pytorch释放显存占用方式
2020/01/13 Python
详解canvas在圆弧周围绘制文本的两种写法
2018/05/22 HTML / CSS
工商局局长个人对照检查材料思想汇报
2014/09/23 职场文书
政府班子四风问题整改措施
2014/10/04 职场文书
单位租房协议书范本
2014/12/04 职场文书
2014保险公司个人工作总结
2014/12/09 职场文书
英语感谢信范文
2015/01/20 职场文书