• MySQL MySQL 8.0进阶操作:JSON


    MySQL - MySQL 8.0进阶操作:JSON

    2019年08月05日 16:43:11 写虫师 β 阅读数 1105

     版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

    文章目录

    此学习文是基于MySQL 8.0写的
    得益于大神朋友的悉心指导解决不少坑,才写出此文,向大神奉上膝盖

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

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

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

    创建一个测试表

    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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    插入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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    检索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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    mysql> select emp_no, details ->> '$.address.pin' pin 
        -> from employees.emp_details;
    +--------+--------+
    | emp_no | pin    |
    +--------+--------+
    |      1 | 560103 |
    +--------+--------+
    1 row in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    JSON函数

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

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    也可以使用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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如何查询一个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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果要检查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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3. 修改

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

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

  • 相关阅读:
    LeetCode449. 序列化和反序列化二叉搜索树
    LeetCode448. 找到所有数组中消失的数字
    一行代码如何隐藏 Linux 进程?
    C语言这么厉害,它自身又是用什么语言写的?
    了解C语言,是否代表了解C ++的一半?
    C语言小白那些不知道的事儿
    6 条 Git 实用技巧
    干货来袭,收藏方便找到该网站
    零基础小白如何入门Shell,快来看看(收藏)这篇大总结!!
    Java用于嵌入式系统的优点和局限
  • 原文地址:https://www.cnblogs.com/grj001/p/12224436.html
Copyright © 2020-2023  润新知