🗂️

MySQLでJSON型を使用する

2022/11/16に公開

はじめに

MySQLではバージョン5.7からJSONをそのまま登録できる「JSON型」が使える様になりました。
この記事ではJSON型の使い方についてまとめていきたいと思います。

テーブルを定義する

JSON型を使ってテーブルを作成します。

CREATE TABLE STORE_TBL (
   ID    INT,
   STORE JSON,
   PRIMARY KEY (ID)
);

JSONデータを登録する

作成したテーブルにデータを登録します。

INSERT INTO STORE_TBL VALUES (1, '{"store_cd":"001", "store_nm":"東店", "staff":{"fulltime":["sato", "hayashi"], "parttime":["shimizu", "ogawa"]}}');
INSERT INTO STORE_TBL VALUES (2, '{"store_cd":"002", "store_nm":"北店", "staff":{"fulltime":["suzuki", "kimura"], "parttime":["nakamura"]}}');
INSERT INTO STORE_TBL VALUES (3, '{"store_cd":"003", "store_nm":"西店", "staff":{"fulltime":["tanaka", "sasaki"]}}');
ID STORE_CD
1 {"staff": {"fulltime": ["sato", "hayashi"], "parttime": ["shimizu", "ogawa"]}, "store_cd": "001", "store_nm": "東店"}
2 {"staff": {"fulltime": ["suzuki", "kimura"], "parttime": ["nakamura"]}, "store_cd": "002", "store_nm": "北店"}
3 {"staff": {"fulltime": ["tanaka", "sasaki"]}, "store_cd": "003", "store_nm": "西店"}

JSONデータを検索する

JSON_EXTRACT関数を使用して特定のkeyの値を取得します。
SELECT JSON_EXTRACT(column, '$.key') FROM TABLE;

mysql> SELECT JSON_EXTRACT(STORE, '$.store_nm') FROM STORE_TBL;
+-----------------------------------+
| JSON_EXTRACT(STORE, '$.store_nm') |
+-----------------------------------+
| "東店"                            |
| "北店"                            |
| "西店"                            |
+-----------------------------------+
3 rows in set (0.00 sec)
mysql> SELECT JSON_EXTRACT(STORE, '$.staff.fulltime') FROM STORE_TBL;
+-----------------------------------------+
| JSON_EXTRACT(STORE, '$.staff.fulltime') |
+-----------------------------------------+
| ["sato", "hayashi"]                     |
| ["suzuki", "kimura"]                    |
| ["tanaka", "sasaki"]                    |
+-----------------------------------------+
3 rows in set (0.00 sec)
mysql> SELECT JSON_EXTRACT(STORE, '$.staff.fulltime[0]') FROM STORE_TBL;
+--------------------------------------------+
| JSON_EXTRACT(STORE, '$.staff.fulltime[0]') |
+--------------------------------------------+
| "sato"                                     |
| "suzuki"                                   |
| "tanaka"                                   |
+--------------------------------------------+
3 rows in set (0.00 sec)

JSON_EXTRACT関数を使用せずに、->"$.key"の形式で取得することも可能です。
SELECT column->"$.key" FROM TABLE;

mysql> SELECT STORE->"$.store_nm" FROM STORE_TBL;
+---------------------+
| STORE->"$.store_nm" |
+---------------------+
| "東店"              |
| "北店"              |
| "西店"              |
+---------------------+
3 rows in set (0.00 sec)
mysql> SELECT STORE->"$.staff.fulltime" FROM STORE_TBL;
+---------------------------+
| STORE->"$.staff.fulltime" |
+---------------------------+
| ["sato", "hayashi"]       |
| ["suzuki", "kimura"]      |
| ["tanaka", "sasaki"]      |
+---------------------------+
3 rows in set (0.00 sec)
mysql> SELECT STORE->"$.staff.fulltime[0]" FROM STORE_TBL;
+------------------------------+
| STORE->"$.staff.fulltime[0]" |
+------------------------------+
| "sato"                       |
| "suzuki"                     |
| "tanaka"                     |
+------------------------------+
3 rows in set (0.00 sec)

ダブルクォートを取り除いて取得したい場合は、JSON_UNQUOTE関数を使用します。

mysql> SELECT JSON_UNQUOTE(STORE->"$.store_nm") FROM STORE_TBL;
+-----------------------------------+
| JSON_UNQUOTE(STORE->"$.store_nm") |
+-----------------------------------+
| 東店                              |
| 北店                              |
| 西店                              |
+-----------------------------------+
3 rows in set (0.00 sec)

JSONを整形して取得したい場合は、JSON_PRETTY関数を使用します。

mysql> SELECT JSON_PRETTY(STORE) FROM STORE_TBL WHERE JSON_EXTRACT(STORE, '$.store_cd') = '001';
+----------------------------------------------+
| JSON_PRETTY(STORE)                           |
+----------------------------------------------+
| {
  "staff": {
    "fulltime": [
      "sato",
      "hayashi"
    ],
    "parttime": [
      "shimizu",
      "ogawa"
    ]
  },
  "store_cd": "001",
  "store_nm": "東店"
}   |
+----------------------------------------------+
1 row in set (0.00 sec)

特定のkeyと値のデータを取得する場合は、JSON_CONTAINS関数を使用します。
JSON_CONTAINS(column, '値', '$.key')  ※指定したKeyと値がある場合は1、ない場合は0を返す

-- staff.fulltimeに"kimura"の値があるstore_nmを取得する
mysql> SELECT JSON_EXTRACT(STORE, '$.store_nm') FROM STORE_TBL WHERE JSON_CONTAINS(STORE, '"kimura"', '$.staff.fulltime');
+-----------------------------------+
| JSON_EXTRACT(STORE, '$.store_nm') |
+-----------------------------------+
| "北店"                            |
+-----------------------------------+
1 row in set (0.00 sec)

特定のパスを含むデータを取得する場合は、JSON_CONTAINS_PATH関数を使用します。
JSON_CONTAINS_PATH(column, one_or_all, '$.key')  ※指定したパスがある場合は1、ない場合は0を返す

-- staff.parttimeの指定があるstore_nmを取得する
mysql> SELECT JSON_EXTRACT(STORE, '$.store_nm') FROM STORE_TBL WHERE JSON_CONTAINS_PATH(STORE, 'one', '$.staff.parttime');
+-----------------------------------+
| JSON_EXTRACT(STORE, '$.store_nm') |
+-----------------------------------+
| "東店"                            |
| "北店"                            |
+-----------------------------------+
2 rows in set (0.00 sec)

JSONデータを更新する

JSON_SET関数を使用して特定のkeyの値を更新します。

-- 更新前のデータを表示
mysql> select JSON_EXTRACT(STORE, '$.staff') FROM STORE_TBL WHERE JSON_EXTRACT(STORE, '$.store_cd') = '002';
+--------------------------------------------------------------+
| JSON_EXTRACT(STORE, '$.staff')                               |
+--------------------------------------------------------------+
| {"fulltime": ["suzuki", "kimura"], "parttime": ["nakamura"]} |
+--------------------------------------------------------------+
1 row in set (0.01 sec)

-- store_cd="002"のstaff.parttimeを'saito'に更新する
mysql> UPDATE STORE_TBL SET STORE = JSON_SET(STORE, '$.staff.parttime[0]', 'saito') WHERE JSON_EXTRACT(STORE, '$.store_cd') = "002";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

-- 更新後のデータを表示
mysql> select JSON_EXTRACT(STORE, '$.staff') FROM STORE_TBL WHERE JSON_EXTRACT(STORE, '$.store_cd') = '002';
+-----------------------------------------------------------+
| JSON_EXTRACT(STORE, '$.staff')                            |
+-----------------------------------------------------------+
| {"fulltime": ["suzuki", "kimura"], "parttime": ["saito"]} |
+-----------------------------------------------------------+
1 row in set (0.00 sec)

JSON_ARRAY_APPEND関数を使用して配列の最後に値を追加します。

-- 追加前のデータを表示
mysql> select JSON_EXTRACT(STORE, '$.staff') FROM STORE_TBL WHERE JSON_EXTRACT(STORE, '$.store_cd') = '002';
+-----------------------------------------------------------+
| JSON_EXTRACT(STORE, '$.staff')                            |
+-----------------------------------------------------------+
| {"fulltime": ["suzuki", "kimura"], "parttime": ["saito"]} |
+-----------------------------------------------------------+
1 row in set (0.00 sec)

-- store_cd="002"のstaff.parttimeに'nakano'を追加する
mysql> UPDATE STORE_TBL SET STORE = JSON_ARRAY_APPEND(STORE, '$.staff.parttime', 'nakano') WHERE JSON_EXTRACT(STORE, '$.store_cd') = "002";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

-- 追加後のデータを表示
mysql> select JSON_EXTRACT(STORE, '$.staff') FROM STORE_TBL WHERE JSON_EXTRACT(STORE, '$.store_cd') = '002';                         
+---------------------------------------------------------------------+  
| JSON_EXTRACT(STORE, '$.staff')                                      |
+---------------------------------------------------------------------+
| {"fulltime": ["suzuki", "kimura"], "parttime": ["saito", "nakano"]} |
+---------------------------------------------------------------------+
1 row in set (0.00 sec)

まとめ

MySQLにはJSONを使う為の様々な関数が用意されており、これらの関数を使用することで、かなり柔軟にデータを操作することが可能になりました。
今回紹介した関数以外にも多くの関数がありますので、興味のある方は、MySQLの公式ドキュメントをご参照ください。

レスキューナウテックブログ

Discussion