mysql中保存并操作json对象

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 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 字符串中所需的键值。第一个参数 jsondocjson 字符串(此处为字段名);第二个参数 $.xJSON Path Syntax (此处的意思为提取键 x 的值)。

2) 整体解读:将表 t1 满足条件的记录中,字段 jsondoc 的值更改为 {"name": "hanhan", "age": 12}。条件:提取 json_docx 值等于 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_docx 所指向数组下标为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中键值对

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

方式一: 使用操作符 ->

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 转换的值字符集为 utf8mb4collationutf8mb4_bin

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

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

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

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
5天前
|
JSON JavaScript 前端开发
JavaScript实现字符串转json对象的方法
JavaScript实现字符串转json对象的方法
|
1月前
|
SQL 运维 关系型数据库
MySQL 中 GRANT 操作会引起复制中断吗?
GRANT 操作并不是一个原子性操作,不管执行成功与否,都会触发一个隐式重载授权表的行为。 在生产环境中需要规范用户创建及授权的操作,不推荐使用 DML 语句去直接变更 mysql.user 表,可能会引发其他的问题,若使用了 DML 语句进行变更, 需要手工执行 flush privileges。
41 4
|
22天前
|
JavaScript 关系型数据库 MySQL
创建nodejs项目并接入mysql,完成用户相关的增删改查的详细操作
创建nodejs项目并接入mysql,完成用户相关的增删改查的详细操作
34 0
|
2月前
|
关系型数据库 MySQL
【mysql技巧】如何在这个mysql语句执行前加个前提,也就是只有表里没有相同数据才进行添加插入操作
【mysql技巧】如何在这个mysql语句执行前加个前提,也就是只有表里没有相同数据才进行添加插入操作
25 1
|
26天前
|
存储 关系型数据库 文件存储
面试题MySQL问题之简单的SELECT操作在MVCC下加锁如何解决
面试题MySQL问题之简单的SELECT操作在MVCC下加锁如何解决
31 2
|
1月前
|
SQL 关系型数据库 MySQL
实时计算 Flink版操作报错合集之从mysql读数据写到hive报错,是什么原因
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
1月前
|
消息中间件 关系型数据库 MySQL
实时计算 Flink版操作报错合集之运行mysql to doris pipeline时报错,该如何排查
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
1月前
|
消息中间件 关系型数据库 MySQL
实时计算 Flink版操作报错合集之整库同步mysql到starRock提交任务异常,该如何处理
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
1月前
|
SQL 关系型数据库 MySQL
「Python入门」python操作MySQL和SqlServer
**摘要:** 了解如何使用Python的pymysql模块与MySQL数据库交互。首先,通过`pip install pymysql`安装模块。pymysql提供与MySQL的连接功能,例如创建数据库连接、执行SQL查询。在设置好MySQL环境后,使用`pymysql.connect()`建立连接,并通过游标执行SQL(如用户登录验证)。注意防止SQL注入,使用参数化查询。增删改操作需调用`conn.commit()`来保存更改。pymssql模块类似,但导入和连接对象创建略有不同。
36 0
「Python入门」python操作MySQL和SqlServer
|
1月前
|
存储 JSON 测试技术
python中json和类对象的相互转化
针对python中类对象和json的相关转化问题, 本文介绍了4种方式,涉及了三个非常强大的python库jsonpickle、attrs和cattrs、pydantic,但是这些库的功能并未涉及太深。在工作中,遇到实际的问题时,可以根据这几种方法,灵活选取。 再回到结构化测试数据的构造,当需要对数据进行建模时,也就是赋予数据业务含义,pydantic应该是首选,目前(2024.7.1)来看,pydantic的生态非常活跃,各种基于pydantic的工具也非常多,建议尝试。