MySQL 5.7.8开始对JSON数据类型的支持,JSON不再以字符串形式存储,而是转换为内部二进制存储格式,能够自动验证JSON内容,无效JSON文档会产生错误。二进制结构能够直接通过键或数组索引查找子对象或嵌套值,而无需遍历整个列。
root@test 10:57: create table tab_json(address json); Query OK, 0 rows affected (0.04 sec) root@test 11:02: insert into tab_json values('{"country":"china","city":"shenzhen"}'); Query OK, 1 row affected (0.01 sec) root@test 11:03: insert into tab_json values('{"country":"china","city":"zhejiang","people":1000000}'); Query OK, 1 row affected (0.00 sec) root@test 11:05: select * from tab_json; +-------------------------------------------------------------+ | address | +-------------------------------------------------------------+ | {"city": "shenzhen", "country": "china"} | | {"city": "zhejiang", "people": 1000000, "country": "china"} | +-------------------------------------------------------------+
JSON_TYPE
JSON_TYPE函数需要传入一个JSON参数,并尝试将其解析为JSON值。如果有效,则返回JSON类型,否则返回错误:
root@test 11:21: SELECT JSON_TYPE('["a", "b", 1]'); +----------------------------+ | JSON_TYPE('["a", "b", 1]') | +----------------------------+ | ARRAY | +----------------------------+ root@test 11:23: SELECT JSON_TYPE('1'); +----------------+ | JSON_TYPE('1') | +----------------+ | INTEGER | +----------------+ root@test 11:23: SELECT JSON_TYPE('"ab"'); +-------------------+ | JSON_TYPE('"ab"') | +-------------------+ | STRING | +-------------------+ root@test 11:23: SELECT JSON_TYPE("ab"); ERROR 3141 (22032): Invalid JSON text in argument 1 to function json_type: "Invalid value." at position 0.
JSON_ARRAY
JSON_ARRARY函数接收值列表,并返回这些值的JSON数组
root@test 11:24: SELECT JSON_ARRAY("shenzhen","shanghai","beijing"); +---------------------------------------------+ | JSON_ARRAY("shenzhen","shanghai","beijing") | +---------------------------------------------+ | ["shenzhen", "shanghai", "beijing"] | +---------------------------------------------+
JSON_OBJECT
JSON_OBJECT函数接收键值对,并返回包含JSON对象
root@test 11:29: SELECT JSON_OBJECT('NAME','LU','AGE',25,'ADDR','SHENZHEN'); +-----------------------------------------------------+ | JSON_OBJECT('NAME','LU','AGE',25,'ADDR','SHENZHEN') | +-----------------------------------------------------+ | {"AGE": 25, "ADDR": "SHENZHEN", "NAME": "LU"} | +-----------------------------------------------------+
JSON_MERGE
JSON_MERGE函数接收两个或多个JSON文档并返回合并的结果
root@test 11:34: SELECT JSON_MERGE('[1,2]','3','4'); +-----------------------------+ | JSON_MERGE('[1,2]','3','4') | +-----------------------------+ | [1, 2, 3, 4] | +-----------------------------+ 1 row in set, 1 warning (0.00 sec)
JSON_EXTRACT
JSON_EXTRACT函数能从JSON文档中查询指定键的值
root@test 13:42: select json_extract(address,'$.city') from test.tab_json; +--------------------------------+ | json_extract(address,'$.city') | +--------------------------------+ | "shenzhen" | | "zhejiang" | +--------------------------------+
也可以使用column->>path的方式获取
root@test 13:37: select address->>"$.city" from test.tab_json; +--------------------+ | address->>"$.city" | +--------------------+ | shenzhen | | zhejiang | +--------------------+
JSON_SET
JSON_SET函数替换现有的值,并添加不存在的值
root@test 13:56: SET @j = '["a", {"b": [true, false]}, [10, 20]]'; Query OK, 0 rows affected (0.00 sec) root@test 13:57: select @j; +---------------------------------------+ | @j | +---------------------------------------+ | ["a", {"b": [true, false]}, [10, 20]] | +---------------------------------------+ 1 row in set (0.00 sec) root@test 13:57: SELECT JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2); +--------------------------------------------+ | JSON_SET(@j, '$[1].b[0]', 1, '$[2][2]', 2) | +--------------------------------------------+ | ["a", {"b": [1, false]}, [10, 20, 2]] | +--------------------------------------------+
JSON_INSERT
JSON_INSERT函数用于添加新值,但不替换现有值
root@test 13:57: SELECT JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2); +-----------------------------------------------+ | JSON_INSERT(@j, '$[1].b[0]', 1, '$[2][2]', 2) | +-----------------------------------------------+ | ["a", {"b": [true, false]}, [10, 20, 2]] | +-----------------------------------------------+
JSON_REPLACE
JSON_REPLACE函数替换现有值,并忽略新值
root@test 14:13: SELECT JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2); +------------------------------------------------+ | JSON_REPLACE(@j, '$[1].b[0]', 1, '$[2][2]', 2) | +------------------------------------------------+ | ["a", {"b": [1, false]}, [10, 20]] | +------------------------------------------------+
JSON_REMOVE
JSON_REMOVE函数删除匹配的值
root@test 14:13: SELECT JSON_REMOVE(@j, '$[2]', '$[1].b[1]'); +--------------------------------------+ | JSON_REMOVE(@j, '$[2]', '$[1].b[1]') | +--------------------------------------+ | ["a", {"b": [true]}] | +--------------------------------------+
数据大小写
通过转换JSON值产生的字符串的字符集为utf8mb4,排序规则为utf8mb4_bin,所以JSON值
root@test 11:42: SET @j = JSON_OBJECT('key', 'value'); Query OK, 0 rows affected (0.00 sec) root@test 11:43: SELECT CHARSET(@j), COLLATION(@j); +-------------+---------------+ | CHARSET(@j) | COLLATION(@j) | +-------------+---------------+ | utf8mb4 | utf8mb4_bin | +-------------+---------------+ root@test 11:39: SELECT JSON_ARRAY('x') = JSON_ARRAY('X'); +-----------------------------------+ | JSON_ARRAY('x') = JSON_ARRAY('X') | +-----------------------------------+ | 0 | +-----------------------------------+
针对true、false或null也同样区分大小写,它们必须始终以小写形式编写
root@test 13:33: SELECT CAST('null' AS JSON); +----------------------+ | CAST('null' AS JSON) | +----------------------+ | null | +----------------------+ 1 row in set (0.00 sec) root@test 13:33: SELECT CAST('NULL' AS JSON); ERROR 3141 (22032): Invalid JSON text in argument 1 to function cast_as_json: "Invalid value." at position 0 root@test 13:33: SELECT ISNULL(null), ISNULL(Null), ISNULL(NULL); +--------------+--------------+--------------+ | ISNULL(null) | ISNULL(Null) | ISNULL(NULL) | +--------------+--------------+--------------+ | 1 | 1 | 1 | +--------------+--------------+--------------+
JSON索引
不能直接对JSON列直接进行索引,只能通过虚拟列来引用JSON中的键值,并创建索引。
root@test 14:16: alter table tab_json add column city varchar(20) GENERATED ALWAYS AS (address->"$.city"); Query OK, 0 rows affected (0.03 sec) Records: 0 Duplicates: 0 Warnings: 0 root@test 14:25: show create table tab_json; +----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | tab_json | CREATE TABLE `tab_json` ( `address` json DEFAULT NULL, `city` varchar(20) COLLATE utf8mb4_unicode_ci GENERATED ALWAYS AS (json_extract(`address`,_utf8mb4'$.city')) VIRTUAL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci | +----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) root@test 14:25: create index idx_city on tab_json(city); Query OK, 0 rows affected (0.03 sec) Records: 0 Duplicates: 0 Warnings: 0 root@test 14:25: explain select address->"$.city" as city from tab_json where city ='shenzhen'; +----+-------------+----------+------------+------+---------------+----------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+----------+------------+------+---------------+----------+---------+-------+------+----------+-------+ | 1 | SIMPLE | tab_json | NULL | ref | idx_city | idx_city | 83 | const | 1 | 100.00 | NULL | +----+-------------+----------+------------+------+---------------+----------+---------+-------+------+----------+-------+
更多关于JSON数据类型的内容参考:JSON Data Type