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 相关文章推荐
数据库连接池
Apr 06 MySQL
MySQL命令行操作时的编码问题详解
Apr 14 MySQL
QT连接MYSQL数据库的详细步骤
Jul 07 MySQL
SQL IDENTITY_INSERT作用案例详解
Aug 23 MySQL
MySQL 如何限制一张表的记录数
Sep 14 MySQL
mysql中int(3)和int(10)的数值范围是否相同
Oct 16 MySQL
MySQL利用UNION连接2个查询排序失效详解
Nov 20 MySQL
Mysql中一千万条数据怎么快速查询
Dec 06 MySQL
MySQL的索引你了解吗
Mar 13 MySQL
一次Mysql update sql不当引起的生产故障记录
Apr 01 MySQL
Mysql调整优化之四种分区方式以及组合分区
Apr 13 MySQL
一文解答什么是MySQL的回表
Aug 05 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
把1316这个数表示成两个数的和,其中一个为13的倍数,另一个是11的倍数,求这两个数。
2011/06/24 PHP
PHP解密Unicode及Escape加密字符串
2015/05/17 PHP
Add a Picture to a Microsoft Word Document
2007/06/15 Javascript
jquery实现倒计时代码分享
2014/06/13 Javascript
javascript中键盘事件用法实例分析
2015/01/30 Javascript
JS实现显示当前日期的实例代码
2018/07/03 Javascript
微信小程序扫描二维码获取信息实例详解
2019/05/07 Javascript
浅谈React Native 传参的几种方式(小结)
2019/05/21 Javascript
Vue使用vue-recoure + http-proxy-middleware + vuex配合promise实现基本的跨域请求封装
2019/10/21 Javascript
微信小程序自定义yPicker组件实现省市区三级联动功能
2020/10/29 Javascript
解决Mint-ui 框架Popup和Datetime Picker组件滚动穿透的问题
2020/11/04 Javascript
Python3实现抓取javascript动态生成的html网页功能示例
2017/08/22 Python
Python KMeans聚类问题分析
2018/02/23 Python
对python创建及引用动态变量名的示例讲解
2018/11/10 Python
python requests 库请求带有文件参数的接口实例
2019/01/03 Python
python-itchat 获取微信群用户信息的实例
2019/02/21 Python
pytorch 求网络模型参数实例
2019/12/30 Python
自定义实现 PyQt5 下拉复选框 ComboCheckBox的完整代码
2020/03/30 Python
python db类用法说明
2020/07/07 Python
python如何用matplotlib创建三维图表
2021/01/26 Python
巴西补充剂和维生素购物网站:Natue
2019/06/17 全球购物
JAVA中运算符的分类及举例
2015/09/12 面试题
电子商务专业实习生自我鉴定
2013/09/24 职场文书
应届生幼儿园求职信
2013/11/12 职场文书
体育教育专业毕业生自荐信
2013/11/15 职场文书
缓刑人员的思想汇报
2014/01/11 职场文书
服务员岗位职责
2014/01/29 职场文书
教育技术学专业职业规划书
2014/03/03 职场文书
高级工程师英文求职信
2014/03/19 职场文书
运动会加油口号
2014/06/07 职场文书
城管执法人员个人对照检查材料思想汇报
2014/09/29 职场文书
30岁前绝不能错过的10本书
2019/08/08 职场文书
使用Spring处理x-www-form-urlencoded方式
2021/11/02 Java/Android
AudioContext 实现音频可视化(web技术分享)
2022/02/24 Javascript
SpringBoot2零基础到精通之数据库专项精讲
2022/03/22 Java/Android
Window server 2012 R2 AD域的组策略相关设置
2022/04/28 Servers