当前位置:首页 > 技术分析 > 正文内容

MySQL实战——JSON数据类型_mysql jsonb类型

ruisui885个月前 (02-08)技术分析17

MySQL JSON类型简介

JavaScript Object Notation(JSON)是一种轻量级的、基于文本的,独立于语言的数据交换格式。它源自ECMAScript编程语言标准。

对于MySQL数据库,我们往往是将它作为一种关系型数据库,存放关系型数据库二维表。其实,从MySQL 5.7.8开始,MySQL已支持JSON数据类型,能够高效访问JSON文档中的数据。可以说是向着NoSQL存储功能迈出了一步。

MySQL 8 大幅改进了对 JSON 的支持,为 schema-less 模式的 JSON 文档提供了多文档事务支持和完整的 ACID 合规性。还添加了基于路径查询参数从 JSON 字段中抽取数据的JSON_EXTRACT()函数,以及用于将数据分别组合到 JSON 数组和对象中的 JSON_ARRAYAGG() 和 JSON_OBJECTAGG()聚合函数。

MySQL数据库原本可以将JSON格式的字符串当做String类型存储,但与之相比,JSON数据类型有以下优势:

(1)自动验证存储在JSON列中的JSON文档。无效的文档会产生错误。

(2)优化了存储格式。存储在JSON类型中的JSON文档被转换为允许对文档元素进行快速读取访问的内部格式。当读取以这种二进制格式存储的JSON值时,不需要从文本内容中解析该值,而能够直接通过键或数组索引查找子对象或嵌套值。

存储JSON文档所需的空间与LONGBLOB或LONGTEXT大致相同;MySQL使用utf8mb4字符集和utf8mb4_bin排序规则处理JSON类型的数据,因为utf8mb4_bin是二进制排序规则,所以JSON值是区分大小写的。

下面介绍JSON类型数据的创建、查询、修改以及相关内置函数。


创建

首先创建一个带有JSON类型字段的表,在一个表中,基本数据类型和JSON类型是可以共存的。示例为了简单起见,创建一个只包含JSON类型字段的表,如下:

create table sys_doc (doc json);

有两种方法将JSON数据存入该表。

  • 第一种方法,使用MySQL JSON_OBJECT()函数,这种方式下,若JSON值原本存在双引号,需要使用反斜杠对每个引号字符进行转义,例如,将如下这个键值对作为JSON数据存入表中:

mascot: The MySQL mascot is a dolphin named "Sakila".

INSERT语句为:

//JSON_OBJECT()函数构造JSON数据对象
//JSON数据内容中原本的引号需要用反斜杠转义
INSERT INTO sys_doc VALUES (JSON_OBJECT("mascot", "Our mascot is a dolphin named \"Sakila\"."));
  • 第二种方法,将JSON字符串作为参数传入INSERT语句,这种情况下,需要使用双反斜杠转义JSON值中原本存在的双引号,如下所示:
//直接将JSON字符串存入JSON类型
//使用双反斜杠可以防止MySQL执行转义处理,而是将字符串文本传递给存储引擎进行处理。
INSERT INTO sys_doc VALUES ('{"mascot": "Our mascot is a dolphin named \\"Sakila\\"."}');

通过执行SELECT,可以看到查询出的JSON列值中存在反斜杠,如下所示:

mysql> SELECT doc FROM sys_doc;
+---------------------------------------------------------+
| doc |
+---------------------------------------------------------+
| {"mascot": "Our mascot is a dolphin named \"Sakila\"."} |
+---------------------------------------------------------+

若要查找这个键值对对应的值,可以使用列路径操作符->,如下:

select doc->"$.mascot" from sys_doc;

查询结果:

"Our mascot is a dolphin named \"Sakila\"."

这个查询结果保留了反斜杠以及值起始位置的引号。要想只显示所需的值,而不包括起始位置引号和转义符,可以使用内联路径运算符->>,如下所示:

select doc->>"$.mascot" from sys_doc;

查询结果:

Our mascot is a dolphin named "Sakila".


查询

将下面这个JSON对象存入上文所建数据库表sys_doc,并以这个JSON对象展示相关JSON函数使用(该示例JSON对象表示了一个学生的高考成绩记录,包括姓名、年龄、总分、语文数学英语以及理综各科分数):

{
    "name":"王小虎",
    "age":17,
    "totalScore":582,
    "gender":"男",
    "chinese":120,
    "math":105,
    "english":118,
    "science":[
        88,
        85,
        66
    ]
}

存入以上JSON数据的INSERT语句为:

//JSON_OBJECT()函数创建JSON数据对象
INSERT INTO sys_doc VALUES (JSON_OBJECT('name', '王小虎', 'age', 17, 'totalScore', 582, 'gender', '男', 'chinese', 120, 'math', 105, 'english', 118, 'science', JSON_ARRAY(88, 85, 66)));


  • 查询“王小虎”同学的总分:
select JSON_EXTRACT(doc, "$.totalScore") from sys_doc WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';


  • 查询“王小虎”同学的物理分数(假设"science":[88,85,66]分别表示理科综合中的物理、化学、生物各科的分数):
select JSON_EXTRACT(doc, "$.science[0]") from sys_doc WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';

可以看到,访问数组元素的位置索引是以0开头的整数。


  • 查询“王小虎”同学的理综各科分数,以下三种方式都实现了相同的效果:
//数组元素索引与to关键字配合使用
select JSON_EXTRACT(doc, "$.science[0 to 2]") from sys_doc WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';
//数组元素索引last关键字
select JSON_EXTRACT(doc, "$.science[last-2 to last]") from sys_doc WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';
//表示全部数组元素的通配符*
select JSON_EXTRACT(doc, "$.science[*]") from sys_doc WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';
  • 除了JSON_EXTRACT()函数,还可以用JSON_VALUE()函数,如下:
//JSON_VALUE()函数查询某个字段的值
select JSON_VALUE(doc, "$.science") FROM sys_doc WHERE JSON_VALUE(doc, "$.name") = '王小虎';


  • 查询出JSON文档中所有的KEY值:
//JSON_KEYS()函数列出JSON中所有key
select JSON_KEYS(doc) from sys_doc WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';


  • 查询出JSON文档中所有的VALUE值:
//通配符查出JSON中所有value
select JSON_EXTRACT(doc, "$.*") from sys_doc WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';

这些JSON相关的函数中,$表示正在操作的文档。下文还将展示更多范例。


修改

  • JSON_REPLACE()函数,将“王小虎”的年龄(age)改为20,“生物”分数修改为100:
//JSON_REPLACE()函数
update sys_doc set doc = JSON_REPLACE(doc, '$.age', 20, '$.science[last]', 100) WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';
  • JSON_SET()函数,将年龄(age)改为21,“生物”分数修改为99
//JSON_SET()函数
update sys_doc set doc = JSON_SET(doc, '$.age', 21, '$.science[last]', 99) WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';

此外,JSON_INSERT()函数也可以实现修改功能,他们三者的区别是函数处理文档中现有值和不存在值的方式不同。具体如下:

  1. JSON_SET()将替换现有路径的值,并为不存在的路径添加值。
  2. JSON_INSERT()添加新值,但不替换现有值。
  3. JSON_REPLACE()替换现有值并忽略新值。


删除

JSON_REMOVE()实现对JSON文档内容删除,参数为一个或多个指定要从文档中删除的值的路径。

  • 删除“王小虎”的年龄(age)、生物科目分数,如下:
//JSON_REMOVE()函数
update sys_doc set doc = JSON_REMOVE(doc, '$.age', '$.science[last]') WHERE JSON_EXTRACT(doc, "$.name") = '王小虎';

删除后的文档如下,没有了“age”字段以及“science”字段中的最后一个分数:

{
    "math": 105,
    "name": "王小虎",
    "gender": "男",
    "chinese": 120,
    "english": 118,
    "science": [
        88,
        85
    ],
    "totalScore": 582
}  


格式化

JSON_PRETTY()以可读格式打印JSON文档,例如:

select JSON_PRETTY('{"name":{"CN":"张三", "EN":"zhangsan"},"science":[120,98,90]}');

将会输入下面格式化的JSON文档:

{
    "name": {
        "CN": "张三",
        "EN": "zhangsan"
    },
    "science": [
        120,
        98,
        90
    ]
}

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/1788.html

标签: json_extract
分享给朋友:

“MySQL实战——JSON数据类型_mysql jsonb类型” 的相关文章

vue中router常见的三种传参方式

目录:我们在使用vue开发的过程中使用router跳转的时候肯定会遇到传参的情况;一般情况就三种传参是最常见的;那我们就来看看都有那几种传参方式吧!第一种:{ path: '/mall:id', name: 'Mall', component:...

SpringCloudalibaba+Vue开发仿社交小程序-青牛白马七香车

Spring Cloud Alibaba和Vue是当今开发领域中最为流行的技术组合之一。本文将介绍如何使用Spring Cloud Alibaba和Vue开发仿社交小程序。download: https://www.97yrbl.com/t-1632.html项目概述本项目是一个仿社交小程序,包括用...

uni-app开发微信小程序和h5应用

#头条创作挑战赛#本文同步本人掘金平台的文章:https://juejin.cn/post/6986465633114259469最近,有个需求需要开发H5应用和微信小程序。如果针对不同的平台开发自己的一套代码,那将是一件很糟糕的事情:如果下次需要兼容支付宝小程序、快应用,那工作量随着平台的添加而...

vue+nginx代理配置,解决跨域问题

举例登录接口,ip地址是随便举例的,实际生成地址域名,不一定是本地ip。前端首页地址是:http://192.168.1.25:8080/#/login,前端登录的地址是:http://192.168.1.25:8080/api/login后端登录接口地址是:http://192.168.1.24:...

vue3 学习笔记 (二)——axios 的使用有变化吗?

本篇文章主要目的就是想告诉我身边,正在学 vue3 或者 准备学 vue3 的同学,vue3中网络请求axios该如何使用,防止接触了一点点 vue3 的同学会有个疑问?生命周期、router 、vux使用都改变了,那 axios 使用有没有啥改变?小姐姐使用 axios 之前,需要先安装好。yar...

「go商城」gin+vue跨域问题

什么是跨域?浏览器有一个安全机制叫同源策略。同源就是指协议、域名、端口都一样,如果任意一项不一致就是不同源。简单点说就是,你的网页URL和你调用的接口URL不是一个地方的,浏览器觉得有安全风险,不想让你使用这个接口的数据。跨域的现象当我们在本地启动前、后端代码进行调试时,如果使用postman等类似...