美文网首页
MySQL之JSON数据类型CRUD

MySQL之JSON数据类型CRUD

作者: 社会我大爷 | 来源:发表于2022-03-03 23:20 被阅读0次

JSON数据类型:

从mysql5.7.8开始开始支持,json数据类型。可以通过客户端创建json字段表并操作检索json对象。

JSON较字符类型优势:

  • json字段以二进制为基础存储,读取时不需要重新解析文档并且json对象的键是逻辑排序的可实现快速检索对象
  • 自动验证json文档是否规范
  • json可存储大字段类似BLOB/TEX并提供原生json函数
  • innodb行锁模式下,json一行存储多个属性值在一定程度上可以减轻rowlock争用

劣势:

  • JSON 数据的存储方式类似于 BLOB/TEXT 在 MySQL 中的存储可能会移动到溢出页中
  • 每当修改JSON文档时会重写整个类型出现写入放大
  • 过于free schema的设计可能导致冗余数据占用内存

json使用建议:max_allowed_packet参数了json存储上限,建议不要超过MB大小,除非是冷归档数据

JSON使用:

0、验证函数:

/*
JSON_VALID(值)
返回0: 无效json
返回1: 有效json
*/
mysql[oldlee] > select JSON_VALID('{"age": "18", "job": "DBA", "name": "zhangsan", "score": "A"} ');                                  
+------------------------------------------------------------------------------+
| JSON_VALID('{"age": "18", "job": "DBA", "name": "zhangsan", "score": "A"} ') |
+------------------------------------------------------------------------------+
|                                                                            1 |
+------------------------------------------------------------------------------+

1、新增:

-- 创建添加数据
mysql[oldlee] > create table t1(id int,info json);
mysql[oldlee] > insert into t1 (id, info) values (1, '{"name":"zhangsan", "age":"18", "score":"A"}');
 
-- 使用函数JSON_OBJECT
mysql[oldlee] > insert into t1 (id, info) values (2, JSON_OBJECT(   "name", "wangwu",   "age", "20",   "score", "0" ));
mysql[oldlee] > select * from t1;
+------+-------------------------------------------------+
| id   | info                                            |
+------+-------------------------------------------------+
|    1 | {"age": "18", "name": "zhangsan", "score": "A"} |
|    2 | {"age": "20", "name": "wangwu", "score": "0"}   |
+------+-------------------------------------------------+
 
-- 如果插入的值不符合json规范直接报错:
mysql[oldlee] > insert into t1 values(1,'hahah');        
ERROR 3140 (22032): Invalid JSON text: "Invalid value." at position 0 in value (or column) 'hahah'.
 
-- 插入数组
mysql[oldlee] > insert into t1 (id, info) values (3, '{"name": "maliu","age": "30","score": "100","course" : ["Python","JAVA","MySQL"] }');
-- 使用函数JSON_ARRAY插入数组
mysql[oldlee] > insert into t1 (id, info)
    -> values (4, JSON_OBJECT(
    ->   "name", "lisi",
    ->   "age", "50",
    ->   "score", "60",
    ->   "course", JSON_ARRAY("PHP","Oracle")
    -> ));
 
mysql[oldlee] > select * from t1;
+------+---------------------------------------------------------------------------------------+
| id   | info                                                                                  |
+------+---------------------------------------------------------------------------------------+
|    1 | {"age": "18", "name": "zhangsan", "score": "A"}                                       |
|    2 | {"age": "20", "name": "wangwu", "score": "0"}                                         |
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]} |
|    4 | {"age": "50", "name": "lisi", "score": "60", "course": ["PHP", "Oracle"]}             |
+------+---------------------------------------------------------------------------------------+

2、查询:

/*
使用JSON_EXTRACT(列,路径表达式)函数
路径表达式:以 $ 符号开头,指定一个点,然后是要查找的属性的名称
*/
mysql[oldlee] > select id,JSON_EXTRACT(info, '$.name') AS name from t1;
+------+------------+
| id   | name       |
+------+------------+
|    1 | "zhangsan" |
|    2 | "wangwu"   |
|    3 | "maliu"    |
|    4 | "lisi"     |
+------+------------+
 
-- 数组查询使用 路径表达式+数组索引
mysql[oldlee] > select id,JSON_EXTRACT(info, '$.course') AS name from t1;   
+------+-----------------------------+
| id   | name                        |
+------+-----------------------------+
|    1 | NULL                        |
|    2 | NULL                        |
|    3 | ["Python", "JAVA", "MySQL"] |
|    4 | ["PHP", "Oracle"]           |
+------+-----------------------------+
 
mysql[oldlee] > select id,JSON_EXTRACT(info, '$.course[0]') AS name from t1;
+------+----------+
| id   | name     |
+------+----------+
|    1 | NULL     |
|    2 | NULL     |
|    3 | "Python" |
|    4 | "PHP"    |
+------+----------+
 
/*
使用JSON_EXTRACT(列,路径表达式) 配合where过滤json数据
*/
mysql[oldlee] > select id,info from t1 where JSON_EXTRACT(info, '$.score') = '100';
+------+---------------------------------------------------------------------------------------+
| id   | info                                                                                  |
+------+---------------------------------------------------------------------------------------+
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]} |
+------+---------------------------------------------------------------------------------------+
 
-- JSON_EXTRACT快捷键:
mysql[oldlee] > select id,info from t1 where info -> '$.score' = '100';                                   
+------+---------------------------------------------------------------------------------------+
| id   | info                                                                                  |
+------+---------------------------------------------------------------------------------------+
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]} |
+------+---------------------------------------------------------------------------------------+
 
/*
使用 JSON_CONTAINS 搜索数据
JSON_CONTAINS(json字段,要搜索的文档[在目标中搜索的可选路径值])
如果存在则返回 1,否则返回 0
*/
mysql[oldlee] > select * from t1;
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
| id   | info                                                                                                                                      |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
|    1 | {"age": "18", "name": "zhangsan", "score": "A"}                                                                                           |
|    2 | {"age": "20", "name": "wangwu", "score": "0"}                                                                                             |
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]}                                                     |
|    4 | {"age": "50", "name": "lisi", "score": "60", "course": ["PHP", "Oracle"]}                                                                 |
|    5 | {"age": "29", "name": "zhaoqi", "extra": [{"company": "xxx"}, {"salary": "20k"}], "score": "80", "course": ["Python", "JAVA", "MySQL"]} |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
 
mysql[oldlee] > SELECT id, JSON_CONTAINS(info, '{"course":"MySQL"}') AS '是否包含' FROM t1;        
+------+--------------+
| id   | 是否包含     |
+------+--------------+
|    1 |            0 |
|    2 |            0 |
|    3 |            1 |
|    4 |            0 |
+------+--------------+
 
-- 使用JSON_OBJECT构造一个json对象并检索
mysql[oldlee] > SELECT id, JSON_CONTAINS(info, JSON_OBJECT("course", "MySQL")) AS '是否包含' FROM t1;
+------+--------------+
| id   | 是否包含     |
+------+--------------+
|    1 |            0 |
|    2 |            0 |
|    3 |            1 |
|    4 |            0 |
+------+--------------+
 
-- 指定检索路径,查找extra是否包含 {"company": "xxx"}
 
mysql[oldlee] > SELECT id, JSON_CONTAINS(info, '{"company": "xxx"}','$.extra') AS info FROM t1;
+------+------+
| id   | info |
+------+------+
|    1 | NULL |
|    2 | NULL |
|    3 | NULL |
|    4 | NULL |
|    5 |    1 |
+------+------+
 
 
/*
JSON_SEARCH 返回搜索值的 属性路径
语法:JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char [, path] ])
 
json_doc:这是要搜索的 JSON 字段或文档
one_or_all:指定“one”在第一次匹配后终止搜索,或指定“all”以返回所有匹配结果
search_str:要在 json_doc 中搜索的字符串
escape_char:在搜索字符串中指定通配符
path:在指定路径中搜索字符串
*/
-- 例如查询成绩为 A的路径:
mysql[oldlee] > SELECT id, JSON_SEARCH(info, 'one', 'A') AS search_result FROM t1; 
+------+---------------+
| id   | search_result |
+------+---------------+
|    1 | "$.score"     |
|    2 | NULL          |
|    3 | NULL          |
|    4 | NULL          |
|    5 | NULL          |
+------+---------------+
 
-- 查询所有包含 MySQL的路径:
mysql[oldlee] > SELECT id, JSON_SEARCH(info, 'all', '%MySQL%') AS search_result FROM t1;
+------+---------------+
| id   | search_result |
+------+---------------+
|    1 | NULL          |
|    2 | NULL          |
|    3 | "$.course[2]" |
|    4 | NULL          |
|    5 | "$.course[2]" |
+------+---------------+
 
/*
JSON_TYPE 查找值的类型
*/
mysql[oldlee] > SELECT '["a", "b", "c"]' AS json_data, JSON_TYPE('["a", "b", "c"]') AS jtype;
+-----------------+-------+
| json_data       | jtype |
+-----------------+-------+
| ["a", "b", "c"] | ARRAY |
+-----------------+-------+

3、更新

/*
JSON_INSERT(json_doc, path, val [, path, val…] ) 将新数据添加到现有 JSON 值并返回更新的 JSON 值,如果更新的key存在则忽略
json_doc:要更新的 JSON 字段
path: 添加新值的路径
val: 为路径添加的值
*/
 
mysql[oldlee] > UPDATE t1 SET info = JSON_INSERT(info, '$.extra','[{"company": "xxx"}]') WHERE id = 1; 
mysql[oldlee] > select * from t1;
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
| id   | info                                                                                                                                      |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
|    1 | {"age": "18", "name": "zhangsan", "extra": "[{"company": "xxx"}]", "score": "A"}                                                        |
|    2 | {"age": "20", "name": "wangwu", "score": "0"}                                                                                             |
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]}                                                     |
|    4 | {"age": "50", "name": "lisi", "score": "60", "course": ["PHP", "Oracle"]}                                                                 |
|    5 | {"age": "29", "name": "zhaoqi", "extra": [{"company": "xxx"}, {"salary": "20k"}], "score": "80", "course": ["Python", "JAVA", "MySQL"]} |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
 
/*
JSON_REPLACE 更新现有值
JSON_REPLACE (json_doc, path, val [, path, val…] )
json_doc:要更新的 JSON 字段
path:更新值的路径
val:要更新的值
*/
 
mysql[oldlee] > UPDATE t1 SET info = JSON_REPLACE(info, '$.extra','[{"company": "xxx"}]') WHERE id = 1;     
mysql[oldlee] > select * from t1;
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
| id   | info                                                                                                                                      |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
|    1 | {"age": "18", "name": "zhangsan", "extra": "[{"company": "xxx"}]", "score": "A"}                                                         |
|    2 | {"age": "20", "name": "wangwu", "score": "0"}                                                                                             |
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]}                                                     |
|    4 | {"age": "50", "name": "lisi", "score": "60", "course": ["PHP", "Oracle"]}                                                                 |
|    5 | {"age": "29", "name": "zhaoqi", "extra": [{"company": "xxx"}, {"salary": "20k"}], "score": "80", "course": ["Python", "JAVA", "MySQL"]} |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
 
/*
JSON_SET 插入和更新,相当于JSON_REPLACE和JSON_INSERT合并功能
JSON_SET (json_doc, path, val [, path, val…] )
json_doc:要更新的 JSON 字段
path:更新值或插入新属性的路径
val:要为属性更新或插入的值
*/
 
mysql[oldlee] > UPDATE t1 SET info = JSON_SET(info, '$.extra','[{"company": "兑吧"}]','$.job','DBA') WHERE id = 1;
mysql[oldlee] > select * from t1;
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
| id   | info                                                                                                                                      |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
|    1 | {"age": "18", "job": "DBA", "name": "zhangsan", "extra": "[{"company": "兑吧"}]", "score": "A"}                                       |
|    2 | {"age": "20", "name": "wangwu", "score": "0"}                                                                                             |
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]}                                                     |
|    4 | {"age": "50", "name": "lisi", "score": "60", "course": ["PHP", "Oracle"]}                                                                 |
|    5 | {"age": "29", "name": "zhaoqi", "extra": [{"company": "xxx"}, {"salary": "20k"}], "score": "80", "course": ["Python", "JAVA", "MySQL"]} |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+

4、删除

4.1、删除一行:和常规sql一样操作

4.2、从json数据中删除属性 update + JSON_REMOVE:

/*
JSON_INSERT(json_doc, path, val [, path, val…] ) 将新数据添加到现有 JSON 值并返回更新的 JSON 值,如果更新的key存在则忽略
json_doc:要更新的 JSON 字段
path: 添加新值的路径
val: 为路径添加的值
*/
 
mysql[oldlee] > UPDATE t1 SET info = JSON_INSERT(info, '$.extra','[{"company": "xxx"}]') WHERE id = 1; 
mysql[oldlee] > select * from t1;
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
| id   | info                                                                                                                                      |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
|    1 | {"age": "18", "name": "zhangsan", "extra": "[{"company": "xxx"}]", "score": "A"}                                                        |
|    2 | {"age": "20", "name": "wangwu", "score": "0"}                                                                                             |
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]}                                                     |
|    4 | {"age": "50", "name": "lisi", "score": "60", "course": ["PHP", "Oracle"]}                                                                 |
|    5 | {"age": "29", "name": "zhaoqi", "extra": [{"company": "xxx"}, {"salary": "20k"}], "score": "80", "course": ["Python", "JAVA", "MySQL"]} |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
 
/*
JSON_REPLACE 更新现有值
JSON_REPLACE (json_doc, path, val [, path, val…] )
json_doc:要更新的 JSON 字段
path:更新值的路径
val:要更新的值
*/
 
mysql[oldlee] > UPDATE t1 SET info = JSON_REPLACE(info, '$.extra','[{"company": "xxx"}]') WHERE id = 1;     
mysql[oldlee] > select * from t1;
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
| id   | info                                                                                                                                      |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
|    1 | {"age": "18", "name": "zhangsan", "extra": "[{"company": "xxx"}]", "score": "A"}                                                         |
|    2 | {"age": "20", "name": "wangwu", "score": "0"}                                                                                             |
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]}                                                     |
|    4 | {"age": "50", "name": "lisi", "score": "60", "course": ["PHP", "Oracle"]}                                                                 |
|    5 | {"age": "29", "name": "zhaoqi", "extra": [{"company": "xxx"}, {"salary": "20k"}], "score": "80", "course": ["Python", "JAVA", "MySQL"]} |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
 
/*
JSON_SET 插入和更新,相当于JSON_REPLACE和JSON_INSERT合并功能
JSON_SET (json_doc, path, val [, path, val…] )
json_doc:要更新的 JSON 字段
path:更新值或插入新属性的路径
val:要为属性更新或插入的值
*/
 
mysql[oldlee] > UPDATE t1 SET info = JSON_SET(info, '$.extra','[{"company": "xxx"}]','$.job','DBA') WHERE id = 1;
mysql[oldlee] > select * from t1;
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
| id   | info                                                                                                                                      |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+
|    1 | {"age": "18", "job": "DBA", "name": "zhangsan", "extra": "[{"company": "xxx"}]", "score": "A"}                                       |
|    2 | {"age": "20", "name": "wangwu", "score": "0"}                                                                                             |
|    3 | {"age": "30", "name": "maliu", "score": "100", "course": ["Python", "JAVA", "MySQL"]}                                                     |
|    4 | {"age": "50", "name": "lisi", "score": "60", "course": ["PHP", "Oracle"]}                                                                 |
|    5 | {"age": "29", "name": "zhaoqi", "extra": [{"company": "xxx"}, {"salary": "20k"}], "score": "80", "course": ["Python", "JAVA", "MySQL"]} |
+------+-------------------------------------------------------------------------------------------------------------------------------------------+

JSON性能优化:

使用虚拟列创建函数索引,虚拟列参考:MySQL之虚拟列

mysql[oldlee] > explain select id,info from t1 where JSON_EXTRACT(info, '$.score') = '100';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    5 |   100.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
 
mysql[oldlee] > ALTER TABLE t1 ADD COLUMN js_score VARCHAR(100) GENERATED ALWAYS AS (JSON_EXTRACT(info, '$.score') );
mysql[oldlee] > CREATE INDEX idx_js_score ON t1(js_score);
 
mysql[oldlee] > explain select id,info from t1 where js_score = '100';                               
+----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key          | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | t1    | NULL       | ref  | idx_js_score  | idx_js_score | 103     | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+--------------+---------+-------+------+----------+-------+

JSON函数参考:

https://dev.mysql.com/doc/refman/8.0/en/json-function-reference.html

相关文章

  • MySQL之JSON数据类型CRUD

    JSON数据类型: 从mysql5.7.8开始开始支持,json数据类型。可以通过客户端创建json字段表并操作检...

  • MySQL处理Json数据

    备注: 版本: MySQL 8.0 一. Json数据存储 MySQL 8.0提供了json数据类型来存储json...

  • SQL中的JSON数据类型

    SQL中的JSON数据类型 概述 MySQL支持原生JSON类型,使用JSON数据类型相较于将JSON格式的字符串...

  • MySQL JSON类型

    MySQL支持JSON数据类型。相比于Json格式的字符串类型,JSON数据类型的优势有: 存储在JSON列中的J...

  • MySQL 5.7起支持JSON数据类型的字段

    MySQL 5.7起支持JSON数据类型的字段。JSON作为现在最为流行的数据交互形式,MySQL也不断跟进,在5...

  • 0328-任务1(DB)总结

    DB设计:数据类型,编码,排序,extra(自增,修改时更新),默认 mysql及工具使用: db,表;CRUD语...

  • mysql和mariadb区别

    mysql提供: JSON 数据类型——从 5.7 版本开始,MySQL 支持由 RFC 7159 定义的原生 J...

  • JSON类型 和 生成列 - 非官方 MySQL 8.0 优化指

    MySQL Server 支持无模式的数据存储,功能特性如下: JSON 数据类型。JSON 值在新增 / 更新时...

  • 19-MySQL-JSON

    转载:谈谈 MySQL 的 JSON 数据类型[https://juejin.cn/post/6872248954...

  • Mysql5.7支持Json数据类型

    JSON support. MySQL5.7.8开始原生支持JSON数据类型,不再以字符串形式存储而是以二进制格式...

网友评论

      本文标题:MySQL之JSON数据类型CRUD

      本文链接:https://www.haomeiwen.com/subject/ggcprrtx.html