MySQL数据库的JSON数据类型详解

文章目录

  • JSON 数据类型意义
  • 存储JSON串
  • 修改JSON串中指定字段的值
  • 查询 JSON 串中的数据
    • 查询 JSON 串中指定字段的值
      • 特殊语法
    • 精确查询
    • 嵌套精确查询
    • 模糊查询
  • 优化 JSON 查询
  • 处理 JSON 数据的常用函数
    • JSON_CONTAINS_PATH
    • JSON_PRETTY
  • 总结
  • 参考资料

JSON 数据类型意义

其实,没有JSON数据类型的支持,我们一样可以通过varchar类型或者text等类型来保存这一格式的数据,但是,为什么还要专门增加这一数据格式的支持呢?其中肯定有较varchar或者text来存储此类型更优越的地方。

1.保证了 JSON 数据类型的强校验,JSON 数据列会自动校验存入此列的内容是否符合 JSON 格式,非正常格式则报错,而 varchar 类型和 text 等类型本身是不存在这种机制的。
2.MySQL 同时提供了一组操作 JSON 类型数据的内置函数。
3.更优化的存储格式,存储在 JSON 列中的 JSON 数据会被转成内部特定的存储格式,允许快速读取。
4.基于 JSON 格式的特征,支持修改指定的字段值。

存储JSON串

insert into commodity(commodity_id,title,current_selling_price,attributes)
values (9,'小米手机',2000,'{"specValueId":"3845862150911746064","specValue":"深红色","specValueType":"红色系","specValueTypeId":"3845862150911746056","specId":"3845862150911746061","specName":"xx颜色","specType":"颜色","extdata1":"rgba(255, 9, 9, 1)","extdata2":"http://localhost:8080/123.png"}');

这里需要提醒的是:
JSON 类型的列存储的数据要么是 NULL,要么必须是 JSON 格式数据,否则会报错。
JSON 数据类型默认值只能是 NULL。

修改JSON串中指定字段的值

可以使用两个内置函数来修改JSON串中指定字段的值,示例如下:

# 将列attributes中的json串中的字段specValue的值设置为‘绿色’
update commodity set attributes = JSON_SET(attributes,'$.specValue','绿色') where title like '%手机';
# 将列attributes中的json串中的字段specValue的值替换为‘yellow’
update commodity set attributes = JSON_REPLACE(attributes,'$.specValue','yellow') where title like '%手机';

查询 JSON 串中的数据

查询 JSON 串中指定字段的值

select JSON_EXTRACT(attributes,'$.specValue') from commodity where commodity_id = 9;

这里要特别注意了,读取json串中指定字段的值,如果该值是字符串则会把双引号也读取出来,可以使用函数 JSON_UNQUOTE() 去掉双引号:

select json_unquote(JSON_EXTRACT(attributes,'$.specValue')) from commodity where commodity_id = 9;

特殊语法

查询列 attributes 中的 json 串中的字段 specValue 的值,可以使用下面两种查询语句:

select attributes->>'$.specValue' from commodity;

或者

select attributes->'$.specValue' from commodity;

精确查询

假设有个名为 player 的表,有个名为 remarks 的 JSON 类型的列,存储的数据格式如下:

{"name":"lisi","age":39,"address":{"city":"rizhao","region":"lanshan"}}

查询 remarks 列中的json串的name字段的值为“zhangsan”的所有记录:

SELECT * FROM `player` WHERE JSON_EXTRACT(`Remarks`, '$.name') = 'zhangsan';

或者

SELECT * FROM `player` WHERE JSON_CONTAINS(Remarks,JSON_OBJECT('name','zhangsan'));

或者

select * from player where json_contains(remarks,'"zhangsan"','$.name');

嵌套精确查询

查询用户居住城市是日照的所有记录:

SELECT * FROM `player` WHERE JSON_EXTRACT(`Remarks`, '$.address.city') = 'rizhao';

模糊查询

查询列 remarks 中的json串中的字段name的值中包含“zhangsan”的所有记录:

SELECT * FROM `player` WHERE JSON_EXTRACT(`Remarks`, '$.name') LIKE '%zhangsan%';

查询列 remarks 中的 json 串中的字段 age 的值大于等于 25 的所有记录:

SELECT * FROM `player` WHERE JSON_EXTRACT(`Remarks`, '$.age') >= 25;

优化 JSON 查询

找出颜色是“绿色”的商品:

select * from commodity where JSON_EXTRACT(attributes,'$.specValue') = 'yellow';

查看执行计划:

explain select * from commodity where JSON_EXTRACT(attributes,'$.specValue') = 'yellow';

在这里插入图片描述
从执行计划可以看到,查询类型是全表扫描,这样的效率是很低的,那么如何优化呢?

按照过往的思路,我们只要设计合理的索引就能避免全表扫描,但是 JSON 列不能创建索引,官方给出的方法是:基于JSON 创建一个生成列(Generated Column),然后基于生成列创建索引,从而达到对 JSON 类型列加索引的效果。

生成列的值在插入数据时不需要设置,MySQL 会根据生成列关联的表达式自动计算填充。

我们分三步进行演示。
第一步,创建生成列:

alter table commodity add column v_spec_value varchar(15) as (attributes->'$.specValue') after attributes;

生成列 v_spec_value 的值根据表达式 attributes->'$.specValue' 自动计算填充。

第二步,为 v_spec_value 创建索引:

alter table commodity add index idx_spec_value  (v_spec_value);

第三步,使用索引字段来查询:

select * from commodity where v_spec_value = '"yellow"';

在查看执行计划:

explain select * from commodity where v_spec_value = '"yellow"';

在这里插入图片描述

有个疑问:根据表达式获取JSON串中指定字段值,如果是字符串类型的,会把双引号也获取到,导致存储时也会将双引号一起存进去,这个问题如何解决呢?

处理 JSON 数据的常用函数

JSON_CONTAINS_PATH

判断 JSON 串中是否有指定的字段。

查询列attributes 中的 json 串中含有字段 specValue的记录数量:

SELECT count(*), JSON_CONTAINS_PATH(attributes, 'all', '$.specValue') cp FROM commodity GROUP BY cp;

查询结果如下:

在这里插入图片描述

mysql> SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}';
mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e'); -- 指定参数one,表示只要json串中含有至少一个指定字段,则返回1,否则返回0
+---------------------------------------------+
| JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e') |
+---------------------------------------------+
|                                           1 |
+---------------------------------------------+
mysql> SELECT JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e'); -- 指定参数all,表示json串中必须含有全部指定的字段才会返回1,否则返回0
+---------------------------------------------+
| JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e') |
+---------------------------------------------+
|                                           0 |
+---------------------------------------------+
mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.c.d');
+----------------------------------------+
| JSON_CONTAINS_PATH(@j, 'one', '$.c.d') |
+----------------------------------------+
|                                      1 |
+----------------------------------------+
mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a.d');
+----------------------------------------+
| JSON_CONTAINS_PATH(@j, 'one', '$.a.d') |
+----------------------------------------+
|                                      0 |
+----------------------------------------+

JSON_PRETTY

返回格式化的 json 数据:

select json_pretty(attributes) from commodity;

格式化后,显示成这样:

{"specId": "3845862150911746061","extdata1": "rgba(255, 9, 9, 1)","extdata2": "http://localhost:8080/123.png","specName": "xx颜色","specType": "颜色","specValue": "yellow","specValueId": "3845862150911746064","specValueType": "红色系","specValueTypeId": "3845862150911746056"
}

总结

JSON 类型是 MySQL 5.7 版本新增的数据类型,用好 JSON 数据类型可以有效解决很多业务中实际问题。最后,我总结下今天的重点内容: 使用 JSON 数据类型,推荐用 MySQL 8.0.17 以上的版本,性能更好,同时也支持 Multi-Valued Indexes。

1.JSON 数据类型的好处是无须预先定义列,数据本身就具有很好的描述性;
2.不要将有明显关系型的数据用 JSON 存储,如用户余额、用户姓名、用户身份证等,这些都是每个用户必须包含的数据;
3.JSON 数据类型推荐用于存储不经常更新的静态数据。

参考资料

1.https://dev.mysql.com/doc/refman/5.7/en/json-functions.html
2.https://zhuanlan.zhihu.com/p/31823258
3.https://dasini.net/blog/2018/07/23/30-mins-with-mysql-json-functions/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高特权级代码段转向低特权级代码段(利用 ret(retf) 指令实现 jmp from ring0 to ring3)

【0】写在前面 0.1)本代码旨在演示 从 ring0 转移到 ring3(即,从高特权级 转移到 低特权级)0.2)本文 只对 与 门相关的 代码进行简要注释,言简意赅;0.3)文末的个人总结是干货&#…

aws 删除ec2实例_如何在AWS中启动EC2实例

aws 删除ec2实例你好朋友, 在本教程中,我们将看到如何立即在AWS中旋转EC2实例。 您应该有权访问AWS控制台。如果您还没有AWS账户,则可以单击此处并在AWS上创建免费套餐。 如何在AWS中启动EC2实例 第1步 : 使用您的凭证登录到您…

python足球射门小游戏_足球射门游戏教案

足球射门游戏教案【篇一:足球射门游戏教案】足球游戏教案任课教师:张旭授课班级:初二(1)班第1次课上课时间:2008-12-1人数:50男(30)女(20)指导教师:彭老师1.运球接力1.足球运球类游戏{ 2.传球射门3.足球打靶…

jQuery 1.9版本之后函数toggle()的轮流执行事件监听器功能被舍弃掉了

文章目录实现隐藏与显示相互切换的效果可以恢复函数 toggle 轮流执行事件监听器的功能toggle()方法主要有两个功能,一是用于绑定两个或多个事件处理器函数,在元素被点击时轮流执行;二是切换元素的显隐状态,如果元素是可见的&#…

不同特权级间代码段的跳转{ 门 + 跳转(jmp + call) + 返回(ret) }

【0】写在前面 0.1)我们讲 CPU的保护机制,它是可靠的多任务运行环境所必须的;0.2) CPU保护机制:分为段级保护 页级保护; 0.2.1)段级保护分为:段限长 limit 检查、段类型 type 检查…

精打细算油盐_Java:ChronicleMap第1部分,精打细算

精打细算油盐用数百万个对象填充HashMap会很快导致诸如内存使用效率低下,性能低下和垃圾回收等问题。 了解如何使用堆外CronicleMap ,其中可以包含数十亿个对象,而对堆的影响很小或没有。 当我们要使用中小型数据集时,内置的Map实…

日志服务器搭建及配置_[ELK入门到实践笔记] 一、通过rsyslog搭建集中日志服务器...

ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案,这是我在ELK学习和实践过程写下的笔记,整理成了一个ELK入门到实践的系列文章,分享出来与大家共勉。本文为该系列文章的第一篇,通过rsyslog搭建集中日志服务器&#…

JavaScript(JS)调用事件监听器(事件处理函数/事件处理程序/事件监听函数)时如何传递参数

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>事件的演示代码</title></head> <body> <input id"bt" type"button" value"test"> <scrip…

x86 的 TSS 任务切换机制

转自&#xff1a;http://blog.chinaunix.net/uid-587665-id-2732907.html 【0】写在前面segment descriptors 构建保护模式下的最基本、最根本的执行环境。system descriptors 则构建保护模式下的核心组件&#xff1a;&#xff11;、TSS descriptor 提供硬件级的进程切换机制&a…

spring安全性_具有PreAuthorize的Spring方法安全性

spring安全性朋友不允许朋友写用户身份验证。 厌倦了管理自己的用户&#xff1f; 立即尝试Okta的API和Java SDK。 数分钟之内即可在任何应用程序中对用户进行身份验证&#xff0c;管理和保护。 本教程将探讨使用Spring Security在Spring Boot中配置身份验证和授权的两种方法。…

animiz动画制作软件_AN动画制作软件

AN基础介绍我们先了解一些基本概念&#xff0c;才能帮助我们更好的进行下面一系列的操作。1.图层。图层就像是含有文字或图形等元素的胶片&#xff0c;一张张按顺序叠放在一起&#xff0c;组合起来形成页面的最终效果。图层可以将页面上的元素精确定位。图层中可以加入文本、图…

关于一致/非一致代码段与TSS 关系的个人看法

【0】概念定义 0.1&#xff09;一致代码段: 简单理解&#xff0c;就是操作系统拿出来被共享的代码段,可以被低特权级的用户直接调用访问的代码&#xff0c; 但是特权级高的程序不允许访问特权级低的数据. 通常这些共享代码&#xff0c;是”不访问”受保护的资源和某些类型异…

python预处理标准化_tensorflow预处理:数据标准化的几种方法

tensorflow预处理&#xff1a;数据标准化的几种方法发布时间&#xff1a;2018-08-09 19:39,浏览次数&#xff1a;1774, 标签&#xff1a;tensorflow数据归一化问题是数据挖掘中特征向量表达时的重要问题&#xff0c;当不同的特征成列在一起的时候&#xff0c;由于特征本身表达方…

三思笔记_使用反射前先三思

三思笔记介绍 有时&#xff0c;作为开发人员&#xff0c;您可能会遇到无法使用new运算符实例化对象的情况&#xff0c;因为其类名称存储在配置XML中的某个位置&#xff0c;或者您需要调用一个名称指定为注释属性的方法。 在这种情况下&#xff0c;您总会有一个答案&#xff1a;…

分页机制总结

【0】写在前面&#xff08;分页机制&#xff09; 0.0&#xff09; source code from orange’s implemention of a os and text description from Zhaojiong’s perfect analysis of Linux kernel and for complete code ,please visit https://github.com/pacosonTang/Orange…

python程序填空题参照代码模板、完善代码_python二级考试操作题11.pdf

综合应用题参照代码模板完善代码&#xff0c;实现下述功能。文件ngchina.html 保持了网页源代码&#xff0c;请将该页面中图片的URL 提取出来,并输出所有图像的URL。习题讲解#P301#读取HTML 文件内容def getHTMLlines(htmlpath):f open(htmlpath,"r",encoding utf-…

Struts2学习笔记

文章目录Struts2 的核心开发包Struts2 配置文件Struts2 域对象Struts2 编程流程Action 组件使用通配符配置 ActionAction 中如何访问 Session通过 ActionContext 对象访问 Session 对象&#xff08;不推荐&#xff09;通过实现 SessionAware 接口访问 sessionAction 如何访问 r…

如何从文件系统中读取文件内容

【0】写在前面 0.0&#xff09; text description from orange’s implemention of a os &#xff0c;文末总结系个人臆测出的干货 【1】intro to FAT12&#xff08;file allocation table 12&#xff09;文件系统格式&#xff08;from Baidu Baike&#xff09; &#xff08;…

java微服务,微在哪_Java:ChronicleMap第3部分,快速微服务

java微服务,微在哪标准Java Maps需要在启动时进行初始化。 了解如何利用可从文件初始化的ChronicleMaps并显着减少微服务启动时间&#xff0c;以及如何在JVM之间共享Maps。 内置的Map实现&#xff08;例如HashMap和ConcurrentHashMap速度很快&#xff0c;但是必须先使用映射进…

excel离散度图表怎么算_Excel数据分析——离散值排除-excel直方图

今天举例的数据继续沿用昨天做出来的结果&#xff0c;至于这组数据还要接着用多久~~可能要混到我讲不下去为止吧~~~我们通过两个不同的拟合公式得到了两组不同的残差值&#xff0c;数据情况如下&#xff1a;有没有觉得看上面那张散点图有点糊啊&#xff1f;没错&#xff0c;问题…