MySQL5.7的JSON基本操作
在新建表时字段类型可以直接设置为json
类型,比如我们创建一张表:
create table `test_user`
(
`id` int primary key auto_increment,
`name` varchar(50) not null,
`info` json
);
json类型字段可以为NULL
insert into test_user(`name`, `info`)
values ('xiaoming', '{
"sex": 1,
"age": 18,
"nick_name": "小萌"
}');
json类型的字段必须时一个有效的json字符串
JSON_OBJECT()
函数构造json对象insert into test_user(`name`, `info`)
values ('xiaohua', json_object("sex", 0, "age", 17));
JSON_ARRAY()
函数构造json数组insert into test_user(`name`, `info`)
values ('xiaozhang', json_object("sex", 1, "age", 19, "tag", json_array(3, 5, 90)));
查看test_user表中的数据:
mysql> select * from test_user;
+----+-----------+----------------------------------------------+
| id | name | info |
+----+-----------+----------------------------------------------+
| 1 | xiaoming | {"age": 18, "sex": 1, "nick_name": "小萌"} |
| 2 | xiaohua | {"age": 17, "sex": 0} |
| 3 | xiaozhang | {"age": 19, "sex": 1, "tag": [3, 5, 90]} |
+----+-----------+----------------------------------------------+
3 rows in set (0.00 sec)
表达式: 对象为json列->'$.键'
, 数组为json列->'$.键[index]'
mysql> select name, info -> '$.nick_name' as nick_name, info -> '$.sex' as sex, info -> '$.tag[0]' as 1st_tag from test_user;
+-----------+-----------+------+---------+
| name | nick_name | sex | 1st_tag |
+-----------+-----------+------+---------+
| xiaoming | "小萌" | 1 | NULL |
| xiaohua | NULL | 0 | NULL |
| xiaozhang | NULL | 1 | 3 |
+-----------+-----------+------+---------+
3 rows in set (0.00 sec)
等价于:对象为JSON_EXTRACT(json列 , '$.键')
,数组为JSON_EXTRACT(json列 , '$.键[index]')
mysql> select name, JSON_EXTRACT(info, '$.nick_name') as nick_name, JSON_EXTRACT(info, '$.sex') as sex, JSON_EXTRACT(info, '$.tag[0]') as 1st_tag from test_user;
+-----------+-----------+------+---------+
| name | nick_name | sex | 1st_tag |
+-----------+-----------+------+---------+
| xiaoming | "小萌" | 1 | NULL |
| xiaohua | NULL | 0 | NULL |
| xiaozhang | NULL | 1 | 3 |
+-----------+-----------+------+---------+
3 rows in set (0.00 sec)
不过看到上面"小萌"
是带双引号的,这不是我们想要的,可以用JSON_UNQUOTE
函数将双引号去掉
mysql> select name, JSON_UNQUOTE(info -> '$.nick_name') as nick_name from test_user where name = 'xiaoming';
+----------+-----------+
| name | nick_name |
+----------+-----------+
| xiaoming | 小萌 |
+----------+-----------+
1 row in set (0.00 sec)
也可以直接使用操作符->>
mysql> select name, info ->> '$.nick_name' as nick_name from test_user where name = 'xiaoming';
+----------+-----------+
| name | nick_name |
+----------+-----------+
| xiaoming | 小萌 |
+----------+-----------+
1 row in set (0.00 sec)
mysql> select name, info ->> '$.nick_name' as nick_name from test_user where info -> '$.nick_name' = '小萌';
+----------+-----------+
| name | nick_name |
+----------+-----------+
| xiaoming | 小萌 |
+----------+-----------+
1 row in set (0.00 sec)
虚拟列
对JSON类型的指定属性进行快速查询。创建虚拟列:
mysql> alter table `test_user` add `nick_name` varchar(50) generated always as (info ->> '$.nick_name') virtual;
注意用操作符->>
去除双引号
删除虚拟列
mysql> alter table `test_user` drop `nick_name`;
使用时和普通类型的列查询是一样:
mysql> select name, nick_name from test_user where nick_name = '小萌';
+----------+-----------+
| name | nick_name |
+----------+-----------+
| xiaoming | 小萌 |
+----------+-----------+
1 row in set (0.00 sec)
JSON_INSERT()
插入新值,但不会覆盖已经存在的值更新前
mysql> select * from test_user where id = 2;
+----+---------+-----------------------+-----------+
| id | name | info | nick_name |
+----+---------+-----------------------+-----------+
| 2 | xiaohua | {"age": 17, "sex": 0} | NULL |
+----+---------+-----------------------+-----------+
1 row in set (0.00 sec)
更新
mysql> update test_user set info = json_insert(info, '$.sex', 1, '$.nick_name', '小花') where id = 2;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
更新后
mysql> select * from test_user where id = 2;
+----+---------+----------------------------------------------+-----------+
| id | name | info | nick_name |
+----+---------+----------------------------------------------+-----------+
| 2 | xiaohua | {"age": 17, "sex": 0, "nick_name": "小花"} | 小花 |
+----+---------+----------------------------------------------+-----------+
1 row in set (0.00 sec)
JSON_SET()
插入新值,并覆盖已经存在的值更新前
mysql> select * from test_user where id = 3;
+----+-----------+------------------------------------------+-----------+
| id | name | info | nick_name |
+----+-----------+------------------------------------------+-----------+
| 3 | xiaozhang | {"age": 19, "sex": 1, "tag": [3, 5, 90]} | NULL |
+----+-----------+------------------------------------------+-----------+
1 row in set (0.00 sec)
更新
mysql> update test_user set info = json_set(info, '$.age', 20, '$.sex', 0, '$.nick_name', '小张') where id = 3;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
更新后
mysql> select * from test_user where id = 3;
+----+-----------+-----------------------------------------------------------------+-----------+
| id | name | info | nick_name |
+----+-----------+-----------------------------------------------------------------+-----------+
| 3 | xiaozhang | {"age": 20, "sex": 0, "tag": [3, 5, 90], "nick_name": "小张"} | 小张 |
+----+-----------+-----------------------------------------------------------------+-----------+
1 row in set (0.00 sec)
JSON_REPLACE()
只替换存在的值更新前
mysql> select * from test_user where id = 2;
+----+---------+----------------------------------------------+-----------+
| id | name | info | nick_name |
+----+---------+----------------------------------------------+-----------+
| 2 | xiaohua | {"age": 17, "sex": 0, "nick_name": "小花"} | 小花 |
+----+---------+----------------------------------------------+-----------+
1 row in set (0.00 sec)
更新
mysql> update test_user set info = json_replace(info, '$.sex', 1, '$.tag', '[1,2,3]') where id = 2;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
更新后
mysql> select * from test_user where id = 2;
+----+---------+----------------------------------------------+-----------+
| id | name | info | nick_name |
+----+---------+----------------------------------------------+-----------+
| 2 | xiaohua | {"age": 17, "sex": 1, "nick_name": "小花"} | 小花 |
+----+---------+----------------------------------------------+-----------+
1 row in set (0.00 sec)
可以看到tag没有更新进去
JSON_REMOVE()
删除JSON元素更新前
mysql> select * from test_user where id = 1;
+----+----------+----------------------------------------------+-----------+
| id | name | info | nick_name |
+----+----------+----------------------------------------------+-----------+
| 1 | xiaoming | {"age": 18, "sex": 1, "nick_name": "小萌"} | 小萌 |
+----+----------+----------------------------------------------+-----------+
1 row in set (0.00 sec)
更新
mysql> update test_user set info = json_remove(info, '$.sex', '$.tag') where id = 1;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1 Changed: 1 Warnings: 0
更新后
mysql> select * from test_user where id = 1;
+----+----------+------------------------------------+-----------+
| id | name | info | nick_name |
+----+----------+------------------------------------+-----------+
| 1 | xiaoming | {"age": 18, "nick_name": "小萌"} | 小萌 |
+----+----------+------------------------------------+-----------+
1 row in set (0.00 sec)