`

【MySQL】处理JSON数据

 
阅读更多

业务需要灵活的数据结构

通常,我们在使用MySQL这类关系型数据库时,会遵守一些准则来设计表结构。

但实际应用场景与“严格的单一准则”是有差距的。因为实际情况中需要考虑多方面的平衡作出妥协。

如,我们刚学完数据库原理时,往往会倾向于努力设计满足BC范式的表结构,或者至少是满足第三范式的表结构。

但当我们在解决实际工程问题时,可能会作出一些无法满足这些范式要求的表结构设计决议。这些设计在当时可能是一个不错的选择(即使事后我们可能会对自己大肆批判)。

如,我们可能会将“start_time”、“end_time”和“elapsed”三个字段共存,其中 elapsed = end_time - start_time 以减少计算量。这就不满足第三范式了

如,我们可能会让“user_id”和“user_name”这两个字段在task记录中共存,以减少连表查询。这就不满足第二范式了

而我们现在要说的JSON类型的字段则导致了“表中表”,不满足第一范式。

 

因为SQL(Structured Query Language,结构化查询语言)式的数据操作方式比较固化,而现实应用中又经常出现灵活性的需求。

虽然有各种NoSQL数据库可以解决很多这方面的问题,但出于各方面成本的考量,有时候我们会将数据都存在MySQL中。即,给部分数据各自分配一个字段固化,并留一个字段存储其它数据复合后的值。

如,对于一个Task表,我们可以将 'id','name',‘type’ 等数据各自分配一个字段固化,

而 'arg' 的结构因为 'type' 的不同也会不同,所以我们可以设置一个 'arg' 字段,存储Task各项参数复合后的数据。

我们可以自定义对这些复合数据字段的解析规则(也就是序列化和反序列化)。当然更多的是选取JSON作为这类字段的数据结构标准。

 

MySQL JSON 类型字段

以前,我们一般选用 MySQL 的 VARCHAR 或 TEXT 等作为这类复合数据字段的类型。

从5.7.8开始,MySQL将 JSON 作为标准的字段类型之一。

与JSON格式的纯文本字段相比,JSON类型的字段有以下优势:

  • 自动校验JSON格式。如果添加的数据不符合JSON规范将会报错。
    • 注意:MySQL中合法的JSON字符串格式与我们通常处理的JSON数据可能有些不同。某些场景下,我们习惯将JSON字符串解析成对象({...})或数组([...]),而不考虑单个值的情况(如:“1”)。
  • 存储格式经过优化。读取JSON内容项的速度更快。
    • 因为MySQL提供的内部数据结构允许通过内容项的key或index直接访问目标数据,而无需将处理其它数据。比以前的上层应用读取整块内容再解析的方式更快。

注:

  • 虽然JSON字段可以存储的数据量很大,但它也受 max_allowed_packet 的限制
  • 不能为JSON字段指定默认值,即JSON字段默认值是NULL
  • 虽然可以通过JSON_EXTRACT方法创建Generated Column字段,再通过该字段创建索引。
    • 但这种做法的意义值得商榷,因为既然把该字段的信息放入JSON字段,可能意味着它并不是一个值得固化的标准属性字段,即使它是Generated Column也显得“污染”太重。

示例

创建表

 

CREATE TABLE `t1` (
  `id` INT NOT NULL,
  `f1` VARCHAR(45) NULL,
  `f2` JSON NULL,
  PRIMARY KEY (`id`));

 

 

创建 JSON 字段数据

  • 方式1:直接将序列化后的JSON文本存入字段
insert into t1 values (1, 'alpha', '{"a":1, "b":"two"}');

 

 

insert into t1 values (1, 'alpha', JSON_OBJECT("a", 1, "b", "two"));
insert into t1 values (2, 'beta', JSON_ARRAY("i1", 2, 3.4));
insert into t1 values (
  1,
  'alpha',
  JSON_MERGE(
    '{"a":1}',
    '{"b":"two"}'
  )
);
insert into t1 values (
  1,
  'alpha',
  JSON_MERGE(
    JSON_OBJECT("a", 1),
    JSON_OBJECT("b", "two")
  )
);
insert into t1 values (
  1,
  'alpha',
  JSON_MERGE(
    JSON_OBJECT("a", 1),
    '{"b": "two"}'
  )
);

 

 

注:

  • 从 MySQL 5.7.22 开始,JSON_MERGE 被 JSON_MERGE_PRESERVE 替代
  • 记得规划好JSON字段内部的业务数据结构,不要被自己搞混
    • 另外,可通过 JSON_TYPE 方法查看JSON字段的类型
select f2, JSON_TYPE(f2) from t1;
+----------------------+---------------+
| f2                   | json_type(f2) |
+----------------------+---------------+
| {"a": 1, "b": "two"} | OBJECT        |
| ["1", 2, 3.4]        | ARRAY         |
+----------------------+---------------+

 

读取 JSON 字段中的内容项

  • 可通过 JSON_EXTRACT 方法获取 JSON 字段中的某部分数据

 

select f2 from t1 where json_extract(f2, '$.b') = 'two';
+----------------------+
| f2                   |
+----------------------+
| {"a": 1, "b": "two"} |
+----------------------+

 

  • 或使用 JSON_EXTRACT 方法的简化形式 ‘->’

 

select f2 from t1 where f2->'$[1]' = 2;
+---------------+
| f2            |
+---------------+
| ["1", 2, 3.4] |
+---------------+

 

 

更改 JSON 字段中的内容项

除了直接将序列化后的JSON文本存入字段外,还可以使用 JSON_INSERTJSON_REPLACEJSON_SETJSON_ARRAY_INSERT 等方法满足不同的需求

 

update t1 set f2 = JSON_INSERT(f2, '$.c', '3') where id=1;
update t1 set f2 = JSON_REPLACE(f2, '$.c', '1+1+1') where id=1;
update t1 set f2 = JSON_SET(f2, '$.c', '1+2') where id=1;

 

  • JSON_INSERT:增加内容项;如果内容项(key)已存在,则不做任何改动
  • JSON_REPLACE:替换内容项;如果内容项(key)不存在,则不做任何改动
  • JSON_SET:设置内容项;如内容项(key)已存在,则替换原值;如果内容项(key)不存在,则添加该内容项

因为有时候JSON字段的原值可能是 NULL(JSON字段默认值是NULL),所以上述方法会失效。这时可以使用 COALESCE 方法指定一个初始值。

 

update t1 set f2 = JSON_SET(COALESCE(f2, '{}'), '$.a', '1') where id=3;

 

 

删除 JSON 字段中的内容项

通过 JSON_REMOVE 方法删除内容项

 

update t1 set f2 = JSON_REMOVE(f2, '$.c') where id=1;

 

*修改部分内容

MySQL 8 会对JSON字段部分内容的修改操作进行优化,它是真的只修改部分内容项,而不是创建一个新的整字段值做整体替换。

 

但是条件比较苛刻:

  • 所更新的字段必须是JSON类型
  • 只能通过 JSON_SET、JSON_REPLACE、JSON_REMOVE 这三个方法对字段进行赋值
  • 且这些方法的输入字段必须是要更新的那个字段
  • 更新操作只能是操作已有的内容项,不能增加内容项
  • 新字段值所占用的存储空间不能比原值多(如果目标字段原来所剩的空间足以满足新增的空间需求,也符合优化条件)

如果将系统变量 binlog_row_value_options 设置为 PARTIAL_JSON,这些部分内容修改的操作也会被记录到 Binary Log 中。

 

 

 

更多MySQL JSON 方法:More

JSON值的比较与排序:Comparison and Ordering of JSON Values (可考虑使用 CAST 方法作为辅助)

分享到:
评论

相关推荐

    MySQL操作之JSON数据类型操作详解

    上一篇文章我们介绍了mysql数据存储过程参数实例详解,今天我们看看MySQL操作之JSON数据类型的相关内容。 概述 mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql...

    Android中通过json向MySql中读写数据的方法

    Android 中通过 JSON 向 MySQL 中读写数据的方法是指在 Android 应用程序中使用 JSON(JavaScript Object Notation)格式将数据上传到 MySQL 数据库中,并从 MySQL 数据库中读取数据。这种方法可以实现 Android 应用...

    MySQL JSON类型字段操作

    1、Java 中动态扩展字段,...但mysql毕竟是关系型数据库,在处理json这种非结构化的数据时,还是比较别扭的。 创建JSON 类似 varchar,设置 JSON 主要将字段的 type 是 json, 不能设置长度,可以是 NULL 但不能有默认值

    mysql(5.6及以下)解析json的方法实例详解

    mysql(5.6及以下)解析json #json解析函数 DELIMITER $$ DROP FUNCTION IF EXISTS `json_extract_c`$$ CREATE FUNCTION `json_extract_c`( details TEXT, required_field VARCHAR (255) ) RETURNS TEXT CHARSET ...

    使用Flex,Java,Json更新Mysql数据【高级篇】

    详细请见:使用Flex,Java,Json更新Mysql数据 。但是有一个问题就是在更新的时候都是发送整个datagrid的dataprovider中信息到数据库,无论有的资料并没有需要更新,这样处理起来效率就很低了。所在在高级篇中我想...

    mysql中数据经处理导入到hbase中

    根据mysql中数据库配置表信息查询mysql中数据,将部分处理为json格式,上传到hbase中。

    递归循环读取省市区json文件数据,并保存到数据库中(很全面)

    递归循环读取省市区json文件数据,并保存到数据库中(很全面) 其中包含代码,json文件,实体类代码。轻松上手

    ext中dwrproxy与json处理数据技术

    ExtJs中使用dwrproxy,和json来处理从数据库里查询出来的数据 其中dwrproxy还支持分页(分页功能没做),将war包下载下来后,直接放在tomcat里,然后启动tomcat就可以了 数据库方面,该项目里用的是mysql,数据文件在...

    mysql8.0.zip

    JSON 支持:MySQL 8.0 引入了对 JSON 格式的原生支持,使得存储、查询和处理 JSON 数据变得更加方便。 更强大的地理空间数据支持:MySQL 8.0 在地理空间数据类型和函数方面有了很多改进,并引入了新的地图和地理空间...

    MySQL5.7中的JSON基本操作指南

    MySQL从5.7版本开始就支持JSON格式的数据,操作用起来挺方便的。 建表 在新建表时字段类型可以直接设置为json类型,比如我们创建一张表: mysql> CREATE TABLE `test_user`(`id` INT PRIMARY KEY AUTO_INCREMENT, ...

    C#利用Json.NET将PHP返回的JSON数据显示到DataGridView

    前几天,将MySQL数据库移到了另外一台主机后,我得到了一个沮丧的惊喜:新的主机不接受...然后再C#应用中处理JSON格式数据。我想与大家分享这个过程。 详情请见博文:http://blog.okbase.net/csharp/archive/816.html

    Python实现的将MySQL中的数据导出至EXCEL文件的工具源代码

    Python实现的将MySQL中的数据导出至EXCEL文件的工具源代码 1.增加了控制台菜单 2.将数据库配置文件生成功能合并进主程序 3.优化代码结构,并对各个函数进行了重构 4.增加了excel.json配置文件,使导出EXCEL的相关...

    android客户端连接远程服务器传递数据

    远程服务器上使用 Servlet 来处理客户端的请求,并返回 JSON 数据给客户端。 Android 客户端连接远程服务器传递数据的步骤: 1. Android 客户端使用 HTTP 协议连接远程服务器,发送请求到 Servlet。 2. Servlet ...

    mysql-connector-java-8.0.30.zip

    最新版本的MySQL Connector/J 8.0.30提供了许多优化和新特性,包括支持MySQL 8.0的新功能,如JSON数据类型和更好的SSL支持。此外,它还提供了更好的性能和可扩展性,以及更好的错误处理和日志记录功能。MySQL ...

    struts1+JSON实例

    涉及了数据(MYSQL)设计,登录实现,以及使用JSON传输数据,Ajax发送请求与处理等,特别适合初学者学习Java WEB的学习材料

    mysql针对字段中换行符\r\n进行查询和删除

    1、应用场景:mysql中某个数据字段包含换行符,导致前台解析json时报错  “Uncaught SyntaxError: Unexpected token in JSON at position 333”; 2、针对以上可将数据粘贴进notepad++查看,其中问题部分json如下所...

    该爬虫爬取拉勾网用户想要查询的地区的python相关招聘信息,并且进行数据处理与分析可视化

    因此,可以从该url获取招聘的相关json数据。 采用post请求,Form Data有三个参数: first : 是否首页 pn:页码 kd:搜索关键字 后面就可以通过requests请求得到想要的json数据。 进行数据筛选,与可视化处理...

    mysql的概要介绍与分析

    MySQL,作为全球最受欢迎的开源关系型数据库管理系统之一,它以强大的性能、高可靠性...随着Oracle公司的支持,MySQL持续进化,引入了如JSON数据类型、窗口函数、Common Table Expression等现代SQL特性,保持与时俱进。

    springbootDemo:Spring Boot + Spring数据JPA + MySql

    在SQL这边选择Spring Data JPA和MySQL Driver 然后在Web 选择Spring Web 按Finish 在专案上面按右键选Properties,选择Project Facets设定后按下Apply and Close 在src/main/resources下的application.properties...

Global site tag (gtag.js) - Google Analytics