mysql中保存并操作json对象

简介: mysql中保存并操作json对象

对于最常使用的数据格式 json 而言,数据库 mysql 提供了保存及一系列操作方法供大家使用,下面我们就来学习一下吧。

1.数据类型

在 mysql5.7 版本之前, json 数据一般使用数据类型 LONGBLOB 或者 LONGTEXT 存储。后来大家「千呼万唤」官方才正式引入了数据类型 JSON。

2.创建json类型字段

1) 创建一个测试数据库 testdb

2) 切换到此数据库下

3) 创建一张表 t1,表中包含一个字段 jsondoc ,其字段类型为 JSON

4) 查看表的构建信息

mysql> create database testdb;
Query OK, 1 row affected (0.03 sec)
mysql> use testdb;
Database changed
mysql> create table t1 (jsondoc JSON);
Query OK, 0 rows affected (0.07 sec)
mysql> show create table t1;
+-------+----------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                         |
+-------+----------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `jsondoc` json DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-------+----------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

3.增删改查

3.1 新增数据

新增三条测试数据

insert into t1 values
    ('{"name":"ethanyan","age":25}'),
    ('{"x": 17, "x": "red"}'),
    ('{"x": 17, "x": "red", "x": [3, 5, 7]}');

当我们插入的 json 中包含多个相同字段,表中只会保存最后一个值。可以看下方查询结果。

mysql> select * from t1;
+---------------------------------+
| jsondoc                         |
+---------------------------------+
| {"age": 25, "name": "ethanyan"} |
| {"x": "red"}                    |
| {"x": [3, 5, 7]}                |
+---------------------------------+
3 rows in set (0.00 sec)

官方文档提示在 8.0.3 版本中有bug,上述同一 json 中相同字段情况,会保存第一个值。小闫使用的版本为8.0.19,此bug已修复,最终效果为保存最后一个值。(按书写的先后顺序确定)

3.2 修改数据

3.2.1 案例一

将数据 {"x": "red"} 修改为 {"name": "hanhan", "age": 12}

update t1 
    set jsondoc='{"name": "hanhan", "age": 12}' 
    where json_extract(jsondoc,"$.x")="red";

1) json_extract() 函数可以根据 JSON Path Syntax 提取json 字符串中所需的键值。第一个参数 jsondoc 为 json 字符串(此处为字段名);第二个参数 $.x 是 JSON Path Syntax (此处的意思为提取键 x 的值)。

2) 整体解读:将表 t1 满足条件的记录中,字段 jsondoc 的值更改为 {"name": "hanhan", "age": 12}。条件:提取 json_doc 中 x 值等于 red 的记录。

3.2.2 案例二

将数据 {"x": [3, 5, 7]} 修改为 {"name": "rose", "age": 18}

update t1 
    set jsondoc='{"name": "rose", "age": 18}' 
    where json_extract(jsondoc,"$.x[0]")=3;

可以看出使用的函数、语法与案例一中大致相同,不同的是 JSON Path Syntax。

1) 如果 json 字符串中某一键值为数组,我们可以通过下标索引 [n] 的方式提取元素。

n 为下标

2) 整体解读:将表 t1 满足条件的记录中,字段 jsondoc 的值更改为 {"name": "rose", "age": 18}。条件:提取 json_doc 中 x 所指向数组下标为0的元素值等于3的记录。

3.3 查询数据

3.3.1 查询全部

我们可以查询全部数据,看上述操作是否已经修改数据。

mysql> select * from t1;
+---------------------------------+
| jsondoc                         |
+---------------------------------+
| {"age": 25, "name": "ethanyan"} |
| {"age": 12, "name": "hanhan"}   |
| {"age": 18, "name": "rose"}     |
+---------------------------------+
3 rows in set (0.00 sec)

3.3.2 查询json中键值对

需求:查询表中字段 jsondoc 中 name 的值。

方式一: 使用操作符 ->

mysql> select jsondoc->"$.name" from t1;
+-------------------+
| jsondoc->"$.name" |
+-------------------+
| "ethanyan"        |
| "hanhan"          |
| "rose"            |
+-------------------+
3 rows in set (0.00 sec)

方式二:使用操作符 ->>

mysql> select jsondoc->>"$.name" from t1;
+--------------------+
| jsondoc->>"$.name" |
+--------------------+
| ethanyan           |
| hanhan             |
| rose               |
+--------------------+
3 rows in set (0.00 sec)

方式三:使用函数 json_extract()

mysql> select json_extract(jsondoc,'$.name') from t1;
+--------------------------------+
| json_extract(jsondoc,'$.name') |
+--------------------------------+
| "ethanyan"                     |
| "hanhan"                       |
| "rose"                         |
+--------------------------------+
3 rows in set (0.00 sec)

注意:

1) 可以看出方式一与方式三效果完全一致,方式二结果中没有双引号

2) 操作符 -> 和 ->> 的左侧为字段名,右侧为 JSON Path Syntax

3.4 删除数据

最后我们删除一条记录:


delete from t1 where json_extract(jsondoc,"$.name")="rose";

4.有关函数

大家应该发现增删改查其实最大的不同在于:有很多函数的使用。除了函数 json_extract() 外,还有哪些呢?一起来看看。更多精彩文章请关注公众号『Pythonnote』或者『全栈技术精选』

4.1 JSON_TYPE

JSON_TYPE函数需要一个 JSON 参数,并尝试将其解析为 JSON 值。如果有效,则返回值的 JSON 类型,否则返回错误。

mysql> select json_type('{"name":"ethanyan"}');
+----------------------------------+
| json_type('{"name":"ethanyan"}') |
+----------------------------------+
| OBJECT                           |
+----------------------------------+
1 row in set (0.00 sec)
mysql> select json_type('[1,"2"]');
+----------------------+
| json_type('[1,"2"]') |
+----------------------+
| ARRAY                |
+----------------------+
1 row in set (0.00 sec)
mysql> select json_type('"hello"');
+----------------------+
| json_type('"hello"') |
+----------------------+
| STRING               |
+----------------------+
1 row in set (0.00 sec)
mysql> select json_type('hello world');
ERROR 3141 (22032): Invalid JSON text in argument 1 to function json_type: "Invalid value." at position 0.

4.2 JSON_ARRAY

此函数会将给定的参数,生成一个数组。

mysql> select json_array('a',1,now());
+----------------------------------------+
| json_array('a',1,now())                |
+----------------------------------------+
| ["a", 1, "2020-03-21 11:50:11.000000"] |
+----------------------------------------+
1 row in set (0.00 sec)

4.3 JSON_OBJECT

此函数会将给定的参数,按照顺序组合为键值对,打包成 json 对象。

mysql> select json_object('name','ethanyan','age',20);
+-----------------------------------------+
| json_object('name','ethanyan','age',20) |
+-----------------------------------------+
| {"age": 20, "name": "ethanyan"}         |
+-----------------------------------------+
1 row in set (0.00 sec)

4.4 JSON_MERGE_PRESERVE

该函数会将多个 json 对象进行合并。

mysql> select json_merge_preserve('[1,2]','{"school":"Qinghua"}');
+-----------------------------------------------------+
| json_merge_preserve('[1,2]','{"school":"Qinghua"}') |
+-----------------------------------------------------+
| [1, 2, {"school": "Qinghua"}]                       |
+-----------------------------------------------------+
1 row in set (0.00 sec)

4.5 JSON_MERGE_PATCH

该函数会将多个 json 对象合并,并去重。我们与函数 4.4 进行比对直观感受一下。

mysql> select
    ->     json_merge_preserve('{"a": 1, "b": 2}', '{"c": 3, "a": 4}', '{"c": 5, "d": 3}') as preserve,
    ->     json_merge_patch('{"a": 3, "b": 2}', '{"c": 3, "a": 4}', '{"c": 5, "d": 3}') as patch\G
*************************** 1. row ***************************
preserve: {"a": [1, 4], "b": 2, "c": [3, 5], "d": 3}
   patch: {"a": 4, "b": 2, "c": 5, "d": 3}
1 row in set (0.00 sec)

4.6 JSON_VALID

验证是否为有效的 json

mysql> select json_valid('{"name":1}');
+--------------------------+
| json_valid('{"name":1}') |
+--------------------------+
|                        1 |
+--------------------------+
1 row in set (0.00 sec)
mysql> select json_valid('null');
+--------------------+
| json_valid('null') |
+--------------------+
|                  1 |
+--------------------+
1 row in set (0.00 sec)
mysql> select json_valid('NULL');
+--------------------+
| json_valid('NULL') |
+--------------------+
|                  0 |
+--------------------+
1 row in set (0.00 sec)

json 中如果为空,可以表示为 "" 或者 null 。请不要写 NULL 或者 Null ,虽然在 sql 语法中可以,但是此数据类型中不行。

4.7 JSON_SET

此函数可以替换现有路径的值,并添加不存在的路径的值。更多精彩文章请关注公众号『Pythonnote』或者『全栈技术精选』

比如有一个变量:


set @j = '["a", {"b": [true, false]}, [10, 20]]';

然后我们使用函数进行操作:

mysql> select json_set(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+--------------------------------------------+
| json_set(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+--------------------------------------------+
| ["a", {"b": [1, false]}, [10, 20, 2]]      |
+--------------------------------------------+
1 row in set (0.00 sec)

4.8 JSON_INSERT

添加一个新的键值对,不会更改已经存在的键值对。

mysql> select json_insert(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+-----------------------------------------------+
| json_insert(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+-----------------------------------------------+
| ["a", {"b": [true, false]}, [10, 20, 2]]      |
+-----------------------------------------------+
1 row in set (0.00 sec)

4.9 JSON_REPLACE

替换已有的键值对,不会添加新的键值对。

mysql> select json_replace(@j, '$[1].b[0]', 1, '$[2][2]', 2);
+------------------------------------------------+
| json_replace(@j, '$[1].b[0]', 1, '$[2][2]', 2) |
+------------------------------------------------+
| ["a", {"b": [1, false]}, [10, 20]]             |
+------------------------------------------------+
1 row in set (0.00 sec)

4.10 JSON_REMOVE

接收 JSON 文档和一个或多个指定要从文档中删除的值的路径。返回值是原始文档减去该文档内存在的路径所选择的值。也就是删除指定键值对。

mysql> select json_remove(@j, '$[2]', '$[1].b[1]', '$[1].b[1]');
+---------------------------------------------------+
| json_remove(@j, '$[2]', '$[1].b[1]', '$[1].b[1]') |
+---------------------------------------------------+
| ["a", {"b": [true]}]                              |
+---------------------------------------------------+
1 row in set (0.00 sec)

5.注意

1) 通过 JSON_OBJECT 转换的值字符集为 utf8mb4,collation 为 utf8mb4_bin

2) utf8mb4 是现在最新版本 mysql 默认的编码格式。更多精彩文章请关注公众号『Pythonnote』或者『全栈技术精选』

3) 原来 mysql 支持的 UTF-8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。最著名的错误便是 Emoji表情插入报错,还有很多不常用的汉字,以及任何新增的 Unicode 字符报错等等。

Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
SQL 运维 关系型数据库
MySQL 中 GRANT 操作会引起复制中断吗?
GRANT 操作并不是一个原子性操作,不管执行成功与否,都会触发一个隐式重载授权表的行为。 在生产环境中需要规范用户创建及授权的操作,不推荐使用 DML 语句去直接变更 mysql.user 表,可能会引发其他的问题,若使用了 DML 语句进行变更, 需要手工执行 flush privileges。
517 4
|
JSON IDE Java
鸿蒙开发:json转对象插件回来了
首先,我重新编译了插件,进行了上传,大家可以下载最新的安装包进行体验了,还是和以前一样,提供了在线版和IDE插件版,两个选择,最新的版本,除了升级了版本,兼容了最新的DevEco Studio ,还做了一层优化,就是针对嵌套对象和属性的生成,使用方式呢,一年前的文章中有过详细的概述,这里呢也简单介绍一下。
466 4
鸿蒙开发:json转对象插件回来了
|
JSON JavaScript 前端开发
JavaScript实现字符串转json对象的方法
JavaScript实现字符串转json对象的方法
|
JavaScript 关系型数据库 MySQL
创建nodejs项目并接入mysql,完成用户相关的增删改查的详细操作
创建nodejs项目并接入mysql,完成用户相关的增删改查的详细操作
500 0
|
JSON 前端开发 JavaScript
json字符串如何转为list对象?
json字符串如何转为list对象?
2411 7
|
JSON JavaScript 前端开发
js如何格式化一个JSON对象?
js如何格式化一个JSON对象?
810 3
|
JSON 前端开发 中间件
React读取properties配置文件转化为json对象并使用在url地址中
本文介绍了如何在React项目中读取properties配置文件,将其内容转化为JSON对象,并在请求URL地址时使用这些配置。文章详细说明了异步读取文件、处理字符串转换为JSON对象的过程,并提供了一个封装函数,用于在发起请求前动态生成配置化的URL地址。
621 1
|
XML JSON JavaScript
JSON对象的stringify()和parse()方法使用
本文阐述了JSON对象的`stringify()`和`parse()`方法的用法,包括如何将JavaScript对象转换为JSON字符串,以及如何将JSON字符串解析回JavaScript对象,并讨论了转换过程中需要注意的事项。
JSON对象的stringify()和parse()方法使用
|
存储 JSON 关系型数据库
MySQL与JSON的邂逅:开启大数据分析新纪元
MySQL与JSON的邂逅:开启大数据分析新纪元
|
JSON 关系型数据库 MySQL
MySQL JSON数据存储结构与操作
通过本文的介绍,我们了解了MySQL中JSON数据类型的基本操作、常用JSON函数、以及如何通过索引和优化来提高查询性能。JSON数据类型为存储和操作结构化数据提供了灵活性和便利性,在现代数据库应用中具有广泛的应用前景。希望本文对您在MySQL中使用JSON数据类型有所帮助。
1772 0

推荐镜像

更多