ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL8.0新特性—JSON增强

2022-04-25 18:31:21  阅读:219  来源: 互联网

标签:no json 特性 JSON MySQL8.0 details address emp


要在MySQL中存储数据,就必须定义数据库和表结构(schema),这是一个主要的限制。为了应对这一点,从MySQL 5.7开始,MySQL支恃了JavaScript对象表示(JavaScriptObject Notation,JSON)数据类型。之前,这类数据不是单独的数据类型,会被存储为字符串。新的JSON数据类型提供了自动验证的JSON文档以及优化的存储格式。

JSON文档以二进制格式存储,它提供以下功能:

  • 对文档元素的快速读取访问。
  • 当服务器再次读取JSON文档时,不需要重新解析文本获取该值。
  • 通过键或数组索引直接查找子对象或嵌套值,而不需要读取文档中的所有值。

一、创建数据

1.1 创建测试表

mysql> create table employees.emp_details (
    -> emp_no int primary key,
    -> details json
    -> );
Query OK, 0 rows affected (0.17 sec)

mysql> desc employees.emp_details;
+---------+---------+------+-----+---------+-------+
| Field   | Type    | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| emp_no  | int(11) | NO   | PRI | NULL    |       |
| details | json    | YES  |     | NULL    |       |
+---------+---------+------+-----+---------+-------+
2 rows in set (0.00 sec)

1.2 插入JSON

mysql> insert into employees.emp_details (emp_no, details)
    -> values ('1',
    -> '{"location":"IN","phone":"+11800000000","email":"abc@example.com","address":{"line1":"abc","line2":"xyz street","city":"Bangalore","pin":"560103"}}'
    -> );
Query OK, 1 row affected (0.13 sec)

mysql> select emp_no, details from employees.emp_details;
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| emp_no | details                                                                                                                                                           |
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|      1 | {"email": "abc@example.com", "phone": "+11800000000", "address": {"pin": "560103", "city": "Bangalore", "line1": "abc", "line2": "xyz street"}, "location": "IN"} |
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

1.3 检索JSON

可以使用->->>运算符检索JSON列的字段:

mysql> select emp_no, details -> '$.address.pin' pin 
    -> from employees.emp_details;
+--------+----------+
| emp_no | pin      |
+--------+----------+
|      1 | "560103" |
+--------+----------+
1 row in set (0.00 sec)

如果不用引号检索数据,可以使用->>运算符(推荐此方式)

mysql> select emp_no, details ->> '$.address.pin' pin 
    -> from employees.emp_details;
+--------+--------+
| emp_no | pin    |
+--------+--------+
|      1 | 560103 |
+--------+--------+
1 row in set (0.00 sec)

二、JSON函数

MySQL提供了许多处理JSON数据的函数,让我们看看最常用的几种函数。

2.1 优雅浏览

想要以优雅的格式显示JSON值,请使用JSON_PRETTY()函数

mysql> select emp_no, json_pretty(details) 
    -> from employees.emp_details\G
*************************** 1. row ***************************
              emp_no: 1
json_pretty(details): {
  "email": "abc@example.com",
  "phone": "+11800000000",
  "address": {
    "pin": "560103",
    "city": "Bangalore",
    "line1": "abc",
    "line2": "xyz street"
  },
  "location": "IN"
}
1 row in set (0.00 sec)

2.2 查找

可以在WHERE子句中使用col ->> path运算符来引用JSON的某一列

mysql> select emp_no, details 
    -> from employees.emp_details 
    -> where details ->> '$.address.pin' = "560103";
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| emp_no | details                                                                                                                                                           |
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|      1 | {"email": "abc@example.com", "phone": "+11800000000", "address": {"pin": "560103", "city": "Bangalore", "line1": "abc", "line2": "xyz street"}, "location": "IN"} |
+--------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

也可以使用JSON_CONTAINS函数查询数据。如果找到了数据,则返回1,否则返回0

mysql> select json_contains(details ->> '$.address.pin',"560103") 
    -> from employees.emp_details;
+-----------------------------------------------------+
| json_contains(details ->> '$.address.pin',"560103") |
+-----------------------------------------------------+
|                                                   1 |
+-----------------------------------------------------+
1 row in set (0.00 sec)

如何查询一个key?使用JSON_CONTAINS_PATH函数检查address.line1是否存在

mysql> select json_contains_path(details, 'one', "$.address.line1") 
    -> from employees.emp_details;
+-------------------------------------------------------+
| json_contains_path(details, 'one', "$.address.line1") |
+-------------------------------------------------------+
|                                                     1 |
+-------------------------------------------------------+
1 row in set (0.00 sec)

one表示至少应该存在一个键,检查address.line1或者address.line2是否存在

mysql> select json_contains_path(details, 'one', "$.address.line1", "$.address.line2") 
    -> from employees.emp_details;
+--------------------------------------------------------------------------+
| json_contains_path(details, 'one', "$.address.line1", "$.address.line2") |
+--------------------------------------------------------------------------+
|                                                                        1 |
+--------------------------------------------------------------------------+
1 row in set (0.00 sec)

如果要检查address.line1或者address.line5是否同时存在,可以使用all,而不是one

mysql> select json_contains_path(details, 'all', "$.address.line1", "$.address.line5") 
    -> from employees.emp_details;
+--------------------------------------------------------------------------+
| json_contains_path(details, 'all', "$.address.line1", "$.address.line5") |
+--------------------------------------------------------------------------+
|                                                                        0 |
+--------------------------------------------------------------------------+
1 row in set (0.00 sec)

2.3 修改

可以使用三种不同的函数来修改数据:JSON_SET()JSON_INSERT()JSON_REPLACE()。在MySQL 8之前的版本中,我们还需要对整个列进行完整的更新,这并不是最佳的方法。

2.3.1 JSON_SET()

替换现有值并添加不存在的值

mysql> update employees.emp_details 
    -> set details = json_set(details, "$.address.pin", "560100", "$.nickname","kai") 
    -> where emp_no = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select emp_no, json_pretty(details) 
    -> from employees.emp_details\G
*************************** 1. row ***************************
              emp_no: 1
json_pretty(details): {
  "email": "abc@example.com",
  "phone": "+11800000000",
  "address": {
    "pin": "560100",
    "city": "Bangalore",
    "line1": "abc",
    "line2": "xyz street"
  },
  "location": "IN",
  "nickname": "kai"
}
1 row in set (0.00 sec)

2.3.2 JSON_INSERT()

插入值,但不替换现有值
在这种情况下,$.address.pin不会被更新,只会添加一个新的字段$.address.line4

mysql> update employees.emp_details 
    -> set details = json_insert(details, "$.address.pin", "560132", "$.address.line4","A Wing") 
    -> where emp_no = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select emp_no, json_pretty(details) 
    -> from employees.emp_details\G
*************************** 1. row ***************************
              emp_no: 1
json_pretty(details): {
  "email": "abc@example.com",
  "phone": "+11800000000",
  "address": {
    "pin": "560100",
    "city": "Bangalore",
    "line1": "abc",
    "line2": "xyz street",
    "line4": "A Wing"
  },
  "location": "IN",
  "nickname": "kai"
}
1 row in set (0.01 sec)

2.3.3 JSON_REPLACE()

仅替换现有值
在这种情况下,$.address.line5不会被添加,只有$.address.pin会被更新

mysql> update employees.emp_details 
    -> set details = json_replace(details, "$.address.pin", "560132", "$.address.line5","Landmark") 
    -> where emp_no = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select emp_no, json_pretty(details) 
    -> from employees.emp_details\G
*************************** 1. row ***************************
              emp_no: 1
json_pretty(details): {
  "email": "abc@example.com",
  "phone": "+11800000000",
  "address": {
    "pin": "560132",
    "city": "Bangalore",
    "line1": "abc",
    "line2": "xyz street",
    "line4": "A Wing"
  },
  "location": "IN",
  "nickname": "kai"
}
1 row in set (0.00 sec)

2.4 删除

JSON_REMOVE能从JSON文档中删除数据

mysql> update employees.emp_details 
    -> set details = json_remove(details, "$.address.line4") 
    -> where emp_no = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select emp_no, json_pretty(details) 
    -> from employees.emp_details\G
*************************** 1. row ***************************
              emp_no: 1
json_pretty(details): {
  "email": "abc@example.com",
  "phone": "+11800000000",
  "address": {
    "pin": "560132",
    "city": "Bangalore",
    "line1": "abc",
    "line2": "xyz street"
  },
  "location": "IN",
  "nickname": "kai"
}
1 row in set (0.00 sec)

2.5 其他函数

JSON_KEYS():获取JSON文档中的所有键

mysql> select json_keys(details),json_keys(details ->> "$.address") 
    -> from employees.emp_details 
    -> where emp_no= 1;
+-------------------------------------------------------+------------------------------------+
| json_keys(details)                                    | json_keys(details ->> "$.address") |
+-------------------------------------------------------+------------------------------------+
| ["email", "phone", "address", "location", "nickname"] | ["pin", "city", "line1", "line2"]  |
+-------------------------------------------------------+------------------------------------+
1 row in set (0.00 sec)

JSON_LENGTH():给出JSON文档中的元素数

mysql> select json_length(details), json_length(details ->> "$.address") 
    -> from employees.emp_details 
    -> where emp_no= 1;
+----------------------+--------------------------------------+
| json_length(details) | json_length(details ->> "$.address") |
+----------------------+--------------------------------------+
|                    5 |                                    4 |
+----------------------+--------------------------------------+
1 row in set (0.00 sec)

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

参考文章

标签:no,json,特性,JSON,MySQL8.0,details,address,emp
来源: https://www.cnblogs.com/ciel717/p/16190694.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有