MySQL JSON Functions

한국 MySQL 사용자그룹

 

김영하

Agenda

  • Why JSON in MySQL?

  • What is JSON?

  • MySQL JSON Functions Overview

  • Where to Test?

  • Real Example

  • 나머지

Why JSON in MySQL?

패러다임의 변화

Data Sources

Protovis.js → D3.js

Data Visualization

Python or R

1. collecting

Data Analysis

3. combining & comparing

2. storaging

4. visualizing

What is JSON?

JSON is ...

  • JavaScript Object Notation
  • the creation of Douglas Crockford
  • 2009.12, 공식적으로 ECMA 표준 ECMA-404로 인정됨
  • ECMAScript-262, 5th ed의 표준화에 반영이 됨
  • the data interchange standard
  • Data Property의 기본형식 : "name":"value"

      {"name":"MySQL"}

JSON SYNTAX

  • Data property들은 comma(,)로 구분{"name":"MySQL","likes":"JSON"}
  • Data object들의 배열[{"name":"Lawrence","likes":"JSON"},{"name":"John","likes":"JQUERY"}]
  • string

  • boolean

  • number

  • null

  • array

  • object

JSON Data Type

Why JSON?

  • JSON Is a Data Interchange Format
  • JSON Is Programming Language Independent
  • JSON Is Based on JavaScript Object Literals
  • JSON can use Arrays
  • JSON is shorter
  • JSON works with more complex data
  • JSON is better standardized than CSV
  • No end tags are required for JSON

JSON vs XML vs CSV

ALL

  • Can store data as values within values
  • Can be used across multiple programming languages
  • Can be fetched and parsed to be used within the code

{
    title : "This is my title.",
    body : "This is the body."
}

{
    'title': 'This is my title.',
    'body': 'This is the body.'
}

{
    "title": "This is my title.",
    "body": "This is the body."
}

Quiz!

어떤 것이 진짜 JSON 형태일까요?

 

 

 

JSON Validator

MySQL JSON functions overview

Support JSON in other RDBMS

  1. Oracle 12c

  2. mariaDB 5.3

  3. MSSQL 2016

  4. DB2 10.5

  • JSON Parser for JSON input
  • Support for all JSON datatypes

        – NULL
        – Numeric
        – Boolean

  • Support for JSON arrays
  • Better indexing without resorting to virtual columns
  • More JSON manipulation functions
  • A proper JSON datatype

        –Enforced UTF8
        –JSON even in the SCHEMA
        –Default JSON output format
          To SELECT a JSON column without having to resort to COLUMN_JSON to get JSON out

아직 부족한 것들

MySQL Functions List

  • json_array()
  • json_object()
  • json_insert()
  • json_remove()
  • json_set()
  • json_replace()
  • json_append()
  • json_merge()
  • json_extract()
  • json_search()
  • json_contains()
  • json_contains_path()
  • json_valid()
  • json_type()
  • json_keys()
  • json_length()
  • json_depth()
  • json_unquote()
  • json_quote()

Where to Test?

docker@mysqlserver:~$ docker pull mysql:5.7.8
docker@mysqlserver:~$ docker run --name mysqljsonfunctions \
                      -e MYSQL_ROOT_PASSWORD=admin -d mysql:5.7.8
fc6790aa50896acda92d9ee380af3683339f2675f670cff36ffc9e0221b67b7a
docker@mysqlserver:~$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
fc6790aa5089        mysql:5.7.8         "/entrypoint.sh mysql"   4 seconds ago       Up 3 seconds        3306/tcp            mysqljsonfunctions
docker@mysqlserver:~$ docker run -it --link mysqljsonfunctions:mysql --rm mysql:5.7.8 \
                      sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"3306" -uroot -p'
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.8-rc MySQL Community Server (GPL)

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4 rows in set (0.00 sec)

mysql> 

Real Example

  • json_array()
  • json_object()
  • json_insert()
  • json_remove()
  • json_set()
  • json_replace()
  • json_append()
  • json_merge()
  • json_extract()
mysql> create table thermostat_model 
    -> (model_id varchar(50) primary key, capabilities json);
Query OK, 0 rows affected (0.21 sec)

mysql> create table thermostat_reading( reading json );
Query OK, 0 rows affected (0.22 sec)

Creating JSON Data (JSON 데이터 생성)

mysql> select json_array( 'programmable','fan', 'ac', 'furnace' ) json_array;
+------------------------------------------+
| json_array                               |
+------------------------------------------+
| ["programmable", "fan", "ac", "furnace"] |
+------------------------------------------+
1 row in set (0.04 sec)

Creating JSON Data (JSON 데이터 생성)

mysql> insert into thermostat_model values
    -> ( 'xyzzy', '[ "programmable","fan", "ac", "furnace" ]' ),
    -> ( 'abc123', '[ "fan", "furnace" ]' );
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from thermostat_model;
+----------+------------------------------------------+
| model_id | capabilities                             |
+----------+------------------------------------------+
| abc123   | ["fan", "furnace"]                       |
| xyzzy    | ["programmable", "fan", "ac", "furnace"] |
+----------+------------------------------------------+
2 rows in set (0.00 sec)

Creating JSON Data (JSON 데이터 생성)

mysql> select json_object
    ->   (
    ->     'device_id', 3001,
    ->     'unixtime', 1428440461,
    ->     'setting', 64.0,
    ->     'current_temp', 62.05
    ->   ) json_object;
+-------------------------------------------------------------------------------------+
| json_object                                                                         |
+-------------------------------------------------------------------------------------+
| {"setting": 64.0, "unixtime": 1428440461, "device_id": 3001, "current_temp": 62.05} |
+-------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

Creating JSON Data (JSON 데이터 생성)

mysql> insert into thermostat_reading values
    -> ( '{ "device_id": 3001, "unixtime": 1428462061, "setting": 69.0, "current_temp": 62.05 }' ),
    -> ( '{ "device_id": 3001, "unixtime": 1428483661, "setting": 64.0, "current_temp": 70.25 }' ),
    -> ( '{ "device_id": 3002, "unixtime": 1428462061, "setting": 68.0, "current_temp": 61.05 }' ),
    -> ( '{ "device_id": 3002, "unixtime": 1428483661, "setting": 62.0, "current_temp": 71.25 }' );
Query OK, 4 rows affected (0.05 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from thermostat_reading;
+-----------------------------------------------------------------------------------+
| reading                                                                           |
+-----------------------------------------------------------------------------------+
| {"setting": 69, "unixtime": 1428462061, "device_id": 3001, "current_temp": 62.05} |
| {"setting": 64, "unixtime": 1428483661, "device_id": 3001, "current_temp": 70.25} |
| {"setting": 68, "unixtime": 1428462061, "device_id": 3002, "current_temp": 61.05} |
| {"setting": 62, "unixtime": 1428483661, "device_id": 3002, "current_temp": 71.25} |
+-----------------------------------------------------------------------------------+
4 rows in set (0.00 sec)

Creating JSON Data (JSON 데이터 생성)

mysql> insert into thermostat_reading values
    -> ( '{"on": true, "setting": 69, "unixtime": 1428548461, "device_id": 3001, "current_temp": 62.05}' ),
    -> ( '{"on": false, "setting": 64, "unixtime": 1428570061, "device_id": 3001, "current_temp": 75.25}' ),
    -> ( '{"on": true, "setting": 68, "unixtime": 1428548461, "device_id": 3002, "current_temp": 61.05}' ),
    -> ( '{"on": false, "setting": 62, "unixtime": 1428570061, "device_id": 3002, "current_temp": 76.25}' );
Query OK, 4 rows affected (0.03 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from thermostat_reading;
+------------------------------------------------------------------------------------------------+
| reading                                                                                        |
+------------------------------------------------------------------------------------------------+
| {"setting": 69, "unixtime": 1428462061, "device_id": 3001, "current_temp": 62.05}              |
| {"setting": 64, "unixtime": 1428483661, "device_id": 3001, "current_temp": 70.25}              |
| {"setting": 68, "unixtime": 1428462061, "device_id": 3002, "current_temp": 61.05}              |
| {"setting": 62, "unixtime": 1428483661, "device_id": 3002, "current_temp": 71.25}              |
| {"on": true, "setting": 69, "unixtime": 1428548461, "device_id": 3001, "current_temp": 62.05}  |
| {"on": false, "setting": 64, "unixtime": 1428570061, "device_id": 3001, "current_temp": 75.25} |
| {"on": true, "setting": 68, "unixtime": 1428548461, "device_id": 3002, "current_temp": 61.05}  |
| {"on": false, "setting": 62, "unixtime": 1428570061, "device_id": 3002, "current_temp": 76.25} |
+------------------------------------------------------------------------------------------------+
8 rows in set (0.00 sec)

Schema Evolution: Adding Data (스키마 진화: 데이터 추가)

mysql> update thermostat_reading set reading = json_insert( reading, '$.on', cast( 'null' as json ) );
Query OK, 4 rows affected (0.05 sec)
Rows matched: 8  Changed: 4  Warnings: 0

mysql> select * from thermostat_reading;
+------------------------------------------------------------------------------------------------+
| reading                                                                                        |
+------------------------------------------------------------------------------------------------+
| {"on": null, "setting": 69, "unixtime": 1428462061, "device_id": 3001, "current_temp": 62.05}  |
| {"on": null, "setting": 64, "unixtime": 1428483661, "device_id": 3001, "current_temp": 70.25}  |
| {"on": null, "setting": 68, "unixtime": 1428462061, "device_id": 3002, "current_temp": 61.05}  |
| {"on": null, "setting": 62, "unixtime": 1428483661, "device_id": 3002, "current_temp": 71.25}  |
| {"on": true, "setting": 69, "unixtime": 1428548461, "device_id": 3001, "current_temp": 62.05}  |
| {"on": false, "setting": 64, "unixtime": 1428570061, "device_id": 3001, "current_temp": 75.25} |
| {"on": true, "setting": 68, "unixtime": 1428548461, "device_id": 3002, "current_temp": 61.05}  |
| {"on": false, "setting": 62, "unixtime": 1428570061, "device_id": 3002, "current_temp": 76.25} |
+------------------------------------------------------------------------------------------------+
8 rows in set (0.00 sec)

Schema Evolution: Adding Data (스키마 진화: 데이터 추가)

mysql> update thermostat_reading set reading = json_remove( reading, '$.on' );
Query OK, 8 rows affected (0.03 sec)
Rows matched: 8  Changed: 8  Warnings: 0

mysql> select * from thermostat_reading;
+-----------------------------------------------------------------------------------+
| reading                                                                           |
+-----------------------------------------------------------------------------------+
| {"setting": 69, "unixtime": 1428462061, "device_id": 3001, "current_temp": 62.05} |
| {"setting": 64, "unixtime": 1428483661, "device_id": 3001, "current_temp": 70.25} |
| {"setting": 68, "unixtime": 1428462061, "device_id": 3002, "current_temp": 61.05} |
| {"setting": 62, "unixtime": 1428483661, "device_id": 3002, "current_temp": 71.25} |
| {"setting": 69, "unixtime": 1428548461, "device_id": 3001, "current_temp": 62.05} |
| {"setting": 64, "unixtime": 1428570061, "device_id": 3001, "current_temp": 75.25} |
| {"setting": 68, "unixtime": 1428548461, "device_id": 3002, "current_temp": 61.05} |
| {"setting": 62, "unixtime": 1428570061, "device_id": 3002, "current_temp": 76.25} |
+-----------------------------------------------------------------------------------+
8 rows in set (0.00 sec)

Schema Evolution: Removing Data (스키마 진화: 데이터 삭제)

mysql> insert into thermostat_reading values
    -> ( '{"spread": 3.95, "setting": 69, "unixtime": 1428634861, "device_id": 3001, "current_temp": 65.05}' ),
    -> ( '{"spread": -12.25, "setting": 64, "unixtime": 1428656461, "device_id": 3001, "current_temp": 76.25}' ),
    -> ( '{"spread": 1.95, "setting": 68, "unixtime": 1428634861, "device_id": 3002, "current_temp": 66.05}' ),
    -> ( '{"spread": -15.25, "setting": 62, "unixtime": 1428656461, "device_id": 3002, "current_temp": 77.25}' );
Query OK, 4 rows affected (0.03 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from thermostat_reading;
+-----------------------------------------------------------------------------------------------------+
| reading                                                                                             |
+-----------------------------------------------------------------------------------------------------+
| {"setting": 69, "unixtime": 1428462061, "device_id": 3001, "current_temp": 62.05}                   |
| {"setting": 64, "unixtime": 1428483661, "device_id": 3001, "current_temp": 70.25}                   |
| {"setting": 68, "unixtime": 1428462061, "device_id": 3002, "current_temp": 61.05}                   |
| {"setting": 62, "unixtime": 1428483661, "device_id": 3002, "current_temp": 71.25}                   |
| {"setting": 69, "unixtime": 1428548461, "device_id": 3001, "current_temp": 62.05}                   |
| {"setting": 64, "unixtime": 1428570061, "device_id": 3001, "current_temp": 75.25}                   |
| {"setting": 68, "unixtime": 1428548461, "device_id": 3002, "current_temp": 61.05}                   |
| {"setting": 62, "unixtime": 1428570061, "device_id": 3002, "current_temp": 76.25}                   |
| {"spread": 3.95, "setting": 69, "unixtime": 1428634861, "device_id": 3001, "current_temp": 65.05}   |
| {"spread": -12.25, "setting": 64, "unixtime": 1428656461, "device_id": 3001, "current_temp": 76.25} |
| {"spread": 1.95, "setting": 68, "unixtime": 1428634861, "device_id": 3002, "current_temp": 66.05}   |
| {"spread": -15.25, "setting": 62, "unixtime": 1428656461, "device_id": 3002, "current_temp": 77.25} |
+-----------------------------------------------------------------------------------------------------+
12 rows in set (0.00 sec)

Schema Evolution: Updating Data (스키마 진화: 데이터 수정)

mysql> update thermostat_reading set reading = json_set
    ->   (
    ->     reading,
    ->     '$.spread',
    ->     cast( json_extract( reading, '$.current_temp' ) as decimal(5,2) ) - cast( json_extract( reading, '$.setting' ) as decimal(5,2) ) 
    ->   );
Query OK, 12 rows affected (0.04 sec)
Rows matched: 12  Changed: 12  Warnings: 0

mysql> select * from thermostat_reading;
+----------------------------------------------------------------------------------------------------+
| reading                                                                                            |
+----------------------------------------------------------------------------------------------------+
| {"spread": -6.95, "setting": 69, "unixtime": 1428462061, "device_id": 3001, "current_temp": 62.05} |
| {"spread": 6.25, "setting": 64, "unixtime": 1428483661, "device_id": 3001, "current_temp": 70.25}  |
| {"spread": -6.95, "setting": 68, "unixtime": 1428462061, "device_id": 3002, "current_temp": 61.05} |
| {"spread": 9.25, "setting": 62, "unixtime": 1428483661, "device_id": 3002, "current_temp": 71.25}  |
| {"spread": -6.95, "setting": 69, "unixtime": 1428548461, "device_id": 3001, "current_temp": 62.05} |
| {"spread": 11.25, "setting": 64, "unixtime": 1428570061, "device_id": 3001, "current_temp": 75.25} |
| {"spread": -6.95, "setting": 68, "unixtime": 1428548461, "device_id": 3002, "current_temp": 61.05} |
| {"spread": 14.25, "setting": 62, "unixtime": 1428570061, "device_id": 3002, "current_temp": 76.25} |
| {"spread": -3.95, "setting": 69, "unixtime": 1428634861, "device_id": 3001, "current_temp": 65.05} |
| {"spread": 12.25, "setting": 64, "unixtime": 1428656461, "device_id": 3001, "current_temp": 76.25} |
| {"spread": -1.95, "setting": 68, "unixtime": 1428634861, "device_id": 3002, "current_temp": 66.05} |
| {"spread": 15.25, "setting": 62, "unixtime": 1428656461, "device_id": 3002, "current_temp": 77.25} |
+----------------------------------------------------------------------------------------------------+
12 rows in set (0.00 sec)

Schema Evolution: Updating Data (스키마 진화: 데이터 수정)

mysql> update thermostat_reading set reading = json_replace
    ->   (
    ->     reading,
    ->     '$.spread',
    ->     cast( json_extract( reading, '$.setting' ) as decimal(5,2) ) - cast( json_extract( reading, '$.current_temp' ) as decimal(5,2) )
    ->   );
Query OK, 12 rows affected (0.04 sec)
Rows matched: 12  Changed: 12  Warnings: 0

mysql> select * from thermostat_reading;
+-----------------------------------------------------------------------------------------------------+
| reading                                                                                             |
+-----------------------------------------------------------------------------------------------------+
| {"spread": 6.95, "setting": 69, "unixtime": 1428462061, "device_id": 3001, "current_temp": 62.05}   |
| {"spread": -6.25, "setting": 64, "unixtime": 1428483661, "device_id": 3001, "current_temp": 70.25}  |
| {"spread": 6.95, "setting": 68, "unixtime": 1428462061, "device_id": 3002, "current_temp": 61.05}   |
| {"spread": -9.25, "setting": 62, "unixtime": 1428483661, "device_id": 3002, "current_temp": 71.25}  |
| {"spread": 6.95, "setting": 69, "unixtime": 1428548461, "device_id": 3001, "current_temp": 62.05}   |
| {"spread": -11.25, "setting": 64, "unixtime": 1428570061, "device_id": 3001, "current_temp": 75.25} |
| {"spread": 6.95, "setting": 68, "unixtime": 1428548461, "device_id": 3002, "current_temp": 61.05}   |
| {"spread": -14.25, "setting": 62, "unixtime": 1428570061, "device_id": 3002, "current_temp": 76.25} |
| {"spread": 3.95, "setting": 69, "unixtime": 1428634861, "device_id": 3001, "current_temp": 65.05}   |
| {"spread": -12.25, "setting": 64, "unixtime": 1428656461, "device_id": 3001, "current_temp": 76.25} |
| {"spread": 1.95, "setting": 68, "unixtime": 1428634861, "device_id": 3002, "current_temp": 66.05}   |
| {"spread": -15.25, "setting": 62, "unixtime": 1428656461, "device_id": 3002, "current_temp": 77.25} |
+-----------------------------------------------------------------------------------------------------+
12 rows in set (0.00 sec)

Schema Evolution: Updating Data (스키마 진화: 데이터 수정)

mysql> update thermostat_model
    ->   set capabilities = json_append( capabilities, '$', 'smart_fan' )
    -> where model_id = 'xyzzy';
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from thermostat_model;
+----------+-------------------------------------------------------+
| model_id | capabilities                                          |
+----------+-------------------------------------------------------+
| abc123   | ["fan", "furnace"]                                    |
| xyzzy    | ["programmable", "fan", "ac", "furnace", "smart_fan"] |
+----------+-------------------------------------------------------+
2 rows in set (0.00 sec)

Schema Evolution: Appending Data (스키마 진화: 데이터 추가)

mysql> update thermostat_model
    ->   set capabilities = json_merge( capabilities, json_array( 'https', 'password_protected', 'intrusion_detection' ) )
    -> where model_id = 'xyzzy';
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from thermostat_model;
+----------+-------------------------------------------------------------------------------------------------------------+
| model_id | capabilities                                                                                                |
+----------+-------------------------------------------------------------------------------------------------------------+
| abc123   | ["fan", "furnace"]                                                                                          |
| xyzzy    | ["programmable", "fan", "ac", "furnace", "smart_fan", "https", "password_protected", "intrusion_detection"] |
+----------+-------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Schema Evolution: Appending Data (스키마 진화: 데이터 추가)

mysql> alter table thermostat_reading
    ->   add column device_id int generated always as ( jsn_extract( reading, '$.device_id' ) ) virtual;
Query OK, 0 rows affected (0.08 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> create index tr_di on thermostat_reading( device_id );
Query OK, 12 rows affected (0.57 sec)
Records: 12  Duplicates: 0  Warnings: 0

mysql> select * from thermostat_reading where device_id = 3001;
+-----------------------------------------------------------------------------------------------------+-----------+
| reading                                                                                             | device_id |
+-----------------------------------------------------------------------------------------------------+-----------+
| {"spread": 6.95, "setting": 69, "unixtime": 1428462061, "device_id": 3001, "current_temp": 62.05}   |      3001 |
| {"spread": -6.25, "setting": 64, "unixtime": 1428483661, "device_id": 3001, "current_temp": 70.25}  |      3001 |
| {"spread": 6.95, "setting": 69, "unixtime": 1428548461, "device_id": 3001, "current_temp": 62.05}   |      3001 |
| {"spread": -11.25, "setting": 64, "unixtime": 1428570061, "device_id": 3001, "current_temp": 75.25} |      3001 |
| {"spread": 3.95, "setting": 69, "unixtime": 1428634861, "device_id": 3001, "current_temp": 65.05}   |      3001 |
| {"spread": -12.25, "setting": 64, "unixtime": 1428656461, "device_id": 3001, "current_temp": 76.25} |      3001 |
+-----------------------------------------------------------------------------------------------------+-----------+
6 rows in set (0.00 sec)

mysql> explain format=JSON select * from thermostat_reading where device_id = 3001\G
*************************** 1. row ***************************
EXPLAIN: {
  "query_block": {
    "select_id": 1,
    "cost_info": {
      "query_cost": "1.44"
    },
    "table": {
      "table_name": "thermostat_reading",
      "access_type": "ref",
      "possible_keys": [
        "tr_di"
      ],
      "key": "tr_di",
      "used_key_parts": [
        "device_id"
      ],
      "key_length": "5",
      "ref": [
        "const"
      ],
      "rows_examined_per_scan": 1,
      "rows_produced_per_join": 1,
      "filtered": "100.00",
      "cost_info": {
        "read_cost": "1.20",
        "eval_cost": "0.24",
        "prefix_cost": "1.44",
        "data_read_per_join": "28"
      },
      "used_columns": [
        "reading",
        "device_id"
      ]
    }
  }
}
1 row in set, 1 warning (0.00 sec)

Schema Evolution: Indexing JSON Data

(스키마 진화: JSON 데이터 인덱싱)

  • json_search()
  • json_contains()
  • json_contains_path()
  • json_valid()
  • json_type()
  • json_keys()
  • json_length()
  • json_depth()
  • json_unquote()
  • json_quote()
mysql> select * from thermostat_reading;
+-----------------------------------------------------------------------------------------------------+-----------+
| reading                                                                                             | device_id |
+-----------------------------------------------------------------------------------------------------+-----------+
| {"spread": 6.95, "setting": 69, "unixtime": 1428462061, "device_id": 3001, "current_temp": 62.05}   |      3001 |
| {"spread": -6.25, "setting": 64, "unixtime": 1428483661, "device_id": 3001, "current_temp": 70.25}  |      3001 |
| {"spread": 6.95, "setting": 68, "unixtime": 1428462061, "device_id": 3002, "current_temp": 61.05}   |      3002 |
| {"spread": -9.25, "setting": 62, "unixtime": 1428483661, "device_id": 3002, "current_temp": 71.25}  |      3002 |
| {"spread": 6.95, "setting": 69, "unixtime": 1428548461, "device_id": 3001, "current_temp": 62.05}   |      3001 |
| {"spread": -11.25, "setting": 64, "unixtime": 1428570061, "device_id": 3001, "current_temp": 75.25} |      3001 |
| {"spread": 6.95, "setting": 68, "unixtime": 1428548461, "device_id": 3002, "current_temp": 61.05}   |      3002 |
| {"spread": -14.25, "setting": 62, "unixtime": 1428570061, "device_id": 3002, "current_temp": 76.25} |      3002 |
| {"spread": 3.95, "setting": 69, "unixtime": 1428634861, "device_id": 3001, "current_temp": 65.05}   |      3001 |
| {"spread": -12.25, "setting": 64, "unixtime": 1428656461, "device_id": 3001, "current_temp": 76.25} |      3001 |
| {"spread": 1.95, "setting": 68, "unixtime": 1428634861, "device_id": 3002, "current_temp": 66.05}   |      3002 |
| {"spread": -15.25, "setting": 62, "unixtime": 1428656461, "device_id": 3002, "current_temp": 77.25} |      3002 |
+-----------------------------------------------------------------------------------------------------+-----------+
12 rows in set (0.00 sec)

thermostat_reading 테이블

mysql> select json_length(reading) from thermostat_reading;
+----------------------+
| json_length(reading) |
+----------------------+
|                    5 |
|                    5 |
|                    5 |
|                    5 |
|                    5 |
|                    5 |
|                    5 |
|                    5 |
|                    5 |
|                    5 |
|                    5 |
|                    5 |
+----------------------+
12 rows in set (0.00 sec)

json_length 사용예제

mysql> select json_depth(reading) from thermostat_reading;
+---------------------+
| json_depth(reading) |
+---------------------+
|                   2 |
|                   2 |
|                   2 |
|                   2 |
|                   2 |
|                   2 |
|                   2 |
|                   2 |
|                   2 |
|                   2 |
|                   2 |
|                   2 |
+---------------------+
12 rows in set (0.00 sec)

json_depth 사용예제

mysql> select json_keys(reading) from thermostat_reading;
+-----------------------------------------------------------------+
| json_keys(reading)                                              |
+-----------------------------------------------------------------+
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
| ["spread", "setting", "unixtime", "device_id", "current_temp"]  |
+-----------------------------------------------------------------+
12 rows in set (0.01 sec)

json_keys 사용예제

mysql> select json_contains_path(reading, 'all', '$.spread') from thermostat_reading;
+------------------------------------------------+
| json_contains_path(reading, 'all', '$.spread') |
+------------------------------------------------+
|                                              1 |
|                                              1 |
|                                              1 |
|                                              1 |
|                                              1 |
|                                              1 |
|                                              1 |
|                                              1 |
|                                              1 |
|                                              1 |
|                                              1 |
|                                              1 |
+------------------------------------------------+
12 rows in set (0.00 sec)

json_contains_path 사용예제

mysql> select json_contains_path(reading, 'all', '$.spread', '$.on') from thermostat_reading;
+--------------------------------------------------------+
| json_contains_path(reading, 'all', '$.spread', '$.on') |
+--------------------------------------------------------+
|                                                      0 |
|                                                      0 |
|                                                      0 |
|                                                      0 |
|                                                      0 |
|                                                      0 |
|                                                      0 |
|                                                      0 |
|                                                      0 |
|                                                      0 |
|                                                      0 |
|                                                      0 |
+--------------------------------------------------------+
12 rows in set (0.00 sec)

json_contains_path 사용예제 2

mysql> select json_contains_path(reading, 'one', '$.spread', '$.on') from thermostat_reading;
+--------------------------------------------------------+
| json_contains_path(reading, 'one', '$.spread', '$.on') |
+--------------------------------------------------------+
|                                                      1 |
|                                                      1 |
|                                                      1 |
|                                                      1 |
|                                                      1 |
|                                                      1 |
|                                                      1 |
|                                                      1 |
|                                                      1 |
|                                                      1 |
|                                                      1 |
|                                                      1 |
+--------------------------------------------------------+
12 rows in set (0.00 sec)

json_contains_path 사용예제 3

mysql> select json_contains(reading, json_object('spread', 6.95)) from thermostat_reading;
+-----------------------------------------------------+
| json_contains(reading, json_object('spread', 6.95)) |
+-----------------------------------------------------+
|                                                   1 |
|                                                   0 |
|                                                   1 |
|                                                   0 |
|                                                   1 |
|                                                   0 |
|                                                   1 |
|                                                   0 |
|                                                   0 |
|                                                   0 |
|                                                   0 |
|                                                   0 |
+-----------------------------------------------------+
12 rows in set (0.00 sec)

json_contains 사용예제

mysql> select json_extract(reading, '$.spread') = 6.95 from thermostat_reading;
+------------------------------------------+
| json_extract(reading, '$.spread') = 6.95 |
+------------------------------------------+
|                                        1 |
|                                        0 |
|                                        1 |
|                                        0 |
|                                        1 |
|                                        0 |
|                                        1 |
|                                        0 |
|                                        0 |
|                                        0 |
|                                        0 |
|                                        0 |
+------------------------------------------+
12 rows in set (0.00 sec)

json_extract 사용예제

mysql> select * from thermostat_model;
+----------+-------------------------------------------------------------------------------------------------------------+
| model_id | capabilities                                                                                                |
+----------+-------------------------------------------------------------------------------------------------------------+
| abc123   | ["fan", "furnace"]                                                                                          |
| xyzzy    | ["programmable", "fan", "ac", "furnace", "smart_fan", "https", "password_protected", "intrusion_detection"] |
+----------+-------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

mysql> select json_contains(capabilities, json_array('ac', 'fan')) from thermostat_model;
+------------------------------------------------------+
| json_contains(capabilities, json_array('ac', 'fan')) |
+------------------------------------------------------+
|                                                    0 |
|                                                    1 |
+------------------------------------------------------+
2 rows in set (0.00 sec)

json_contains 사용예제 2

mysql> insert into thermostat_model values
    -> ( "Acme basic", '[{"rpm": 2000, "voltage": 110, "capability": "fan"}, "furnace"]' ),                   
    -> ( "Acme super", '["programmable", {"rpm": 3000, "voltage": 220, "capability": "fan"}, "ac", "furnace"]' );
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from thermostat_model;
+------------+-------------------------------------------------------------------------------------------------------------+
| model_id   | capabilities                                                                                                |
+------------+-------------------------------------------------------------------------------------------------------------+
| abc123     | ["fan", "furnace"]                                                                                          |
| Acme basic | [{"rpm": 2000, "voltage": 110, "capability": "fan"}, "furnace"]                                             |
| Acme super | ["programmable", {"rpm": 3000, "voltage": 220, "capability": "fan"}, "ac", "furnace"]                       |
| xyzzy      | ["programmable", "fan", "ac", "furnace", "smart_fan", "https", "password_protected", "intrusion_detection"] |
+------------+-------------------------------------------------------------------------------------------------------------+
4 rows in set (0.00 sec)

Complex Feature 사용예제

mysql> select json_contains(capabilities, json_array('furnace', json_object('voltage', 110))) from thermostat_model;
+---------------------------------------------------------------------------------+
| json_contains(capabilities, json_array('furnace', json_object('voltage', 110))) |
+---------------------------------------------------------------------------------+
|                                                                               0 |
|                                                                               1 |
|                                                                               0 |
|                                                                               0 |
+---------------------------------------------------------------------------------+
4 rows in set (0.00 sec)

Complex Feature 사용예제 계속

mysql> select json_search(capabilities, 'one', 'furnace') from thermostat_model;
+---------------------------------------------+
| json_search(capabilities, 'one', 'furnace') |
+---------------------------------------------+
| "$[1]"                                      |
| "$[1]"                                      |
| "$[3]"                                      |
| "$[3]"                                      |
+---------------------------- ----------------+
4 rows in set (0.00 sec)

json_search 사용예제

mysql> select json_type(capabilities), json_type(json_extract(capabilities, '$[0]')) from thermostat_model;
+-------------------------+-----------------------------------------------+
| json_type(capabilities) | json_type(json_extract(capabilities, '$[0]')) |
+-------------------------+-----------------------------------------------+
| ARRAY                   | STRING                                        |
| ARRAY                   | OBJECT                                        |
| ARRAY                   | STRING                                        |
| ARRAY                   | STRING                                        |
+-------------------------+-----------------------------------------------+
4 rows in set (0.01 sec)

json_type 사용예제

mysql> select case( json_type( json_extract(capabilities, '$[0]')))
    ->            when "OBJECT" then json_extract( json_extract(capabilities, '$[0]'), '$.capability')
    ->            else json_extract(capabilities, '$[0]')
    ->            end as cap from thermostat_model;
+----------------+
| cap            |
+----------------+
| "fan"          |
| "fan"          |
| "programmable" |
| "programmable" |
+----------------+
4 rows in set (0.00 sec)

json_type 사용예제 2

mysql> select json_valid('{"capability": fan, "rpm": 3000, "voltage": 220}');
+----------------------------------------------------------------+
| json_valid('{"capability": fan, "rpm": 3000, "voltage": 220}') |
+----------------------------------------------------------------+
|                                                              0 |
+----------------------------------------------------------------+
1 row in set (0.03 sec)

json_valid 예제

mysql> select cast('{"capability": fan, "rpm": 3000, "voltage": 220}' as json);
ERROR 3141 (22032): Invalid JSON text in argument 1 to function cast_as_json: "Invalid value" at position 17 in '{"capability": fan, "rpm": 3000, "voltage": 220}'.

Invalid CAST 예제

mysql> select json_valid('{"capability": "fan", "rpm": 3000, "voltage": 220}');
+------------------------------------------------------------------+
| json_valid('{"capability": "fan", "rpm": 3000, "voltage": 220}') |
+------------------------------------------------------------------+
|                                                                1 |
+------------------------------------------------------------------+
1 row in set (0.00 sec)

json_valid 예제

mysql> create table t(doc1 json, doc2 json);
Query OK, 0 rows affected (0.20 sec)

mysql> insert into t values('[1,2,3]', json_quote('[1,2,3]'));
Query OK, 1 row affected (0.03 sec)

mysql> select doc1, json_type(doc1), doc2, json_type(doc2) from t;
+-----------+-----------------+-----------+-----------------+
| doc1      | json_type(doc1) | doc2      | json_type(doc2) |
+-----------+-----------------+-----------+-----------------+
| [1, 2, 3] | ARRAY           | "[1,2,3]" | STRING          |
+-----------+-----------------+-----------+-----------------+
1 row in set (0.00 sec)

json_quote 예제

mysql> select json_extract('{"userName": "fred"}', '$.userName');
+----------------------------------------------------+
| json_extract('{"userName": "fred"}', '$.userName') |
+----------------------------------------------------+
| "fred"                                             |
+----------------------------------------------------+
1 row in set (0.00 sec)

mysql> select json_extract('{"userName":"fred"}', '$.userName') = 'fred';
+------------------------------------------------------------+
| json_extract('{"userName":"fred"}', '$.userName') = 'fred' |
+------------------------------------------------------------+
|                                                          1 |
+------------------------------------------------------------+
1 row in set (0.00 sec)

JSON 비교 예제

mysql> select json_unquote(json_extract('{"userName": "fred" }', '$.userName')) = 'fred';
+----------------------------------------------------------------------------+
| json_unquote(json_extract('{"userName": "fred" }', '$.userName')) = 'fred' |
+----------------------------------------------------------------------------+
|                                                                          1 |
+----------------------------------------------------------------------------+
1 row in set (0.00 sec)

json_unquote으로 JSON 비교 예제

나머지

감사합니다!

MySQL JSON Functions

By fermat39

MySQL JSON Functions

MySQL JSON Functions

  • 3,372