This slide based on https://dev.mysql.com/doc/refman/8.0/en/json.html
MySQL 从 5.7 开始引入了 JSON 类型.
CREATE TABLE my_table ( id INT PRIMARY KEY, json_data JSON );
INSERT INTO my_table (id, json_data) VALUES (1, '{"key1": "value1", "key2": "value2"}');
mysql> select * from my_table; +----+--------------------------------------+ | id | json_data | +----+--------------------------------------+ | 1 | {"key1": "value1", "key2": "value2"} | +----+--------------------------------------+ 1 row in set (0.00 sec)
mysql> SELECT length(json_data) FROM my_table WHERE id=1; +-------------------+ | length(json_data) | +-------------------+ | 36 | +-------------------+ 1 row in set (0.04 sec)
要取出 json_data 这列中
mysql> SELECT JSON_EXTRACT(json_data, '$.key1') FROM my_table; +-----------------------------------+ | JSON_EXTRACT(json_data, '$.key1') | +-----------------------------------+ | "value1" | +-----------------------------------+ 1 row in set (0.00 sec)
下面是 MySQL 5.7.23 中的
mysql> SHOW VARIABLES LIKE "%max_allowed%"; +--------------------------+------------+ | Variable_name | Value | +--------------------------+------------+ | max_allowed_packet | 1048576 | | slave_max_allowed_packet | 1073741824 | +--------------------------+------------+ 2 rows in set, 1 warning (0.01 sec)
在 MySQL 8.4.2 中,
mysql> show variables like "%max_allowed%"; +----------------------------+------------+ | Variable_name | Value | +----------------------------+------------+ | max_allowed_packet | 67108864 | | mysqlx_max_allowed_packet | 67108864 | | replica_max_allowed_packet | 1073741824 | | slave_max_allowed_packet | 1073741824 | +----------------------------+------------+ 4 rows in set, 1 warning (0.21 sec)
JSON 数组(JSON array)是指用中括号界定的以逗号为间隔符的有限个值组成的序列. 这些值可以是字符串、数值、布尔值、null、time、date、datetime 或JSON对象.
这里
JSON 对象 (JSON object) 是指以花括号界定的以逗号为间隔符的有限个键值对组成的序列. 这里键值对形如 "key":"value" 或 "key":10 等. 这里的键必须是字符串, 值可以是字符串、数值、null、JSON数组.
例如:
JSON 数组和 JSON 对象可以包含象字符串或数值的数量值(scalar value)、JSON的字面null、JSON的字面布尔值(true和false).
JSON 对象中的键必须是字符串. 允许使用临时(日期、时间或日期时间)的标量值:
JSON数组中的元素可以是JSON对象, 而JSON对象中的键值对, 其值又可以是JSON数组. 因此允许合法的嵌套. 例如:
[99, {"id": "HK500", "cost": 75.99}, ["hot", "cold"]] {"k1": "value", "k2": [10, 20]}
在插入数据到某一JSON类型的列时, 如果所插入的字符串被验证不是 JSON 类型, 则返回错误.
mysql> INSERT INTO my_table (id, json_data) -> VALUE (2, '[1, 2,'); ERROR 3140 (22032): Invalid JSON text: "Invalid value." at position 6 in value for column 'my_table.json_data'.
mysql> INSERT INTO my_table (id, json_data) -> VALUE (2, '["hello", 0, true, NULL, false]'); ERROR 3140 (22032): Invalid JSON text: "Invalid value." at position 19 in value for column 'my_table.json_data'.
这里应使用小写的
mysql> INSERT INTO my_table (id, json_data) -> VALUE (2, '["hello", 0, true, null, false]'); Query OK, 1 row affected (0.00 sec)
mysql> SELECT JSON_TYPE('["a", "b", 1]'); +----------------------------+ | JSON_TYPE('["a", "b", 1]') | +----------------------------+ | ARRAY | +----------------------------+ 1 row in set (0.00 sec)
mysql> SELECT JSON_TYPE('"hello"'); +----------------------+ | JSON_TYPE('"hello"') | +----------------------+ | STRING | +----------------------+ 1 row in set (0.00 sec)
注意这里字符串一定要用双引号界定, 外面再用单引号界定. 其他形式都不正确.
mysql> SELECT JSON_TYPE('["a", 'b', 1]'); ERROR 1064 (42000): Erreur de syntaxe près de 'b', 1]')' à la ligne 1 mysql> SELECT JSON_TYPE("['a', 'b', 1]"); ERROR 3141 (22032): Invalid JSON text in argument 1 to function json_type: "Invalid value." at position 1.
mysql> SELECT JSON_TYPE('hello'); ERROR 3141 (22032): Invalid JSON text in argument 1 to function json_type: "Invalid value." at position 0. mysql> SELECT JSON_TYPE("'hello'"); ERROR 3141 (22032): Invalid JSON text in argument 1 to function json_type: "Invalid value." at position 0. mysql> SELECT JSON_TYPE(""hello""); ERROR 1064 (42000): Erreur de syntaxe près de '"")' à la ligne 1 mysql> SELECT JSON_TYPE(''hello''); ERROR 1064 (42000): Erreur de syntaxe près de ''')' à la ligne 1
MySQL 8.0 处理 JSON 字符串时使用的字符集是
使用其他字符集的字符串会被转换为
JSON_ARRAY()函数将一列值转换为一个 JSON 数组.
mysql> SELECT JSON_ARRAY('a', 1, NOW()); +----------------------------------------+ | JSON_ARRAY('a', 1, NOW()) | +----------------------------------------+ | ["a", 1, "2024-12-04 11:02:53.000000"] | +----------------------------------------+ 1 row in set (0.02 sec)
如果参数为空, 则返回空的JSON数组.
mysql> SELECT JSON_ARRAY(); +--------------+ | JSON_ARRAY() | +--------------+ | [] | +--------------+ 1 row in set (0.00 sec)
JSON_OBJECT()函数将一列键值对转换为一个包含这一列键值对的JSON对象.
如果参数为空, 则返回空的JSON对象.
mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc'); +---------------------------------------+ | JSON_OBJECT('key1', 1, 'key2', 'abc') | +---------------------------------------+ | {"key1": 1, "key2": "abc"} | +---------------------------------------+ 1 row in set (0.04 sec)
mysql> SELECT JSON_OBJECT(); +---------------+ | JSON_OBJECT() | +---------------+ | {} | +---------------+ 1 row in set (0.00 sec)
如果参数个数不是偶数个, 则返回错误.
mysql> SELECT JSON_OBJECT('key1', 1, 'key2', 'abc', 'key3'); ERROR 1582 (42000): Incorrect parameter count in the call to native function 'JSON_OBJECT'
mysql> SELECT JSON_MERGE_PRESERVE('["a", 1]', '{"key": "value"}'); +-----------------------------------------------------+ | JSON_MERGE_PRESERVE('["a", 1]', '{"key": "value"}') | +-----------------------------------------------------+ | ["a", 1, {"key": "value"}] | +-----------------------------------------------------+ 1 row in set (0.04 sec)
如果是若干个JSON对象进行合并, 则合并成单个对象, 其成员是各JSON对象的键值对.
mysql> SELECT JSON_MERGE_PRESERVE('{"pi": 3.1415926}', '{"key": "value"}'); +--------------------------------------------------------------+ | JSON_MERGE_PRESERVE('{"pi": 3.1415926}', '{"key": "value"}') | +--------------------------------------------------------------+ | {"pi": 3.1415926, "key": "value"} | +--------------------------------------------------------------+ 1 row in set (0.00 sec)
关于合并规则, 参见 Normalization, Merging, and Autowrapping of JSON Values
用户变量可以存储JSON值.
mysql> SET @j = JSON_OBJECT('country', 'China'); Query OK, 0 rows affected (0.00 sec) mysql> select @j; +----------------------+ | @j | +----------------------+ | {"country": "China"} | +----------------------+ 1 row in set (0.00 sec)
需要注意的是, 尽管这里用户变量
当分配给变量时,
mysql> SET @k = JSON_OBJECT('key','value'); Query OK, 0 rows affected (0.00 sec) mysql> select @j, @k; +----------------------+------------------+ | @j | @k | +----------------------+------------------+ | {"country": "China"} | {"key": "value"} | +----------------------+------------------+ 1 row in set (0.00 sec)
将这两个变量进行合并.
mysql> select JSON_merge_preserve(@j, @k); +--------------------------------------+ | JSON_merge_preserve(@j, @k) | +--------------------------------------+ | {"key": "value", "country": "China"} | +--------------------------------------+ 1 row in set (0.00 sec) mysql> select database(); +------------+ | database() | +------------+ | NULL | +------------+ 1 row in set (0.00 sec)
JSON_MERGE_PRESERVE() 在合并JSON对象时, 对键值对中的键进行排序.
mysql> select JSON_MERGE_PRESERVE(@k, @j); +--------------------------------------+ | JSON_merge_preserve(@k, @j) | +--------------------------------------+ | {"key": "value", "country": "China"} | +--------------------------------------+ 1 row in set (0.00 sec)
mysql> SET @L = JSON_OBJECT('1', 'math'); Query OK, 0 rows affected (0.02 sec) mysql> SELECT JSON_MERGE_PRESERVE(@j, @k, @L); +---------------------------------------------------+ | JSON_MERGE_PRESERVE(@j, @k, @L) | +---------------------------------------------------+ | {"1": "math", "key": "value", "country": "China"} | +---------------------------------------------------+ 1 row in set (0.00 sec) mysql> SET @m = JSON_OBJECT("case", "[2,true,null]"); Query OK, 0 rows affected (0.00 sec) mysql> select JSON_MERGE_PRESERVE(@j, @k, @L, @m); +----------------------------------------------------------------------------+ | JSON_MERGE_PRESERVE(@j, @k, @L, @m) | +----------------------------------------------------------------------------+ | {"1": "math", "key": "value", "case": "[2,true,NULL]", "country": "China"} | +----------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> select JSON_MERGE_PRESERVE(@k, @m, @j, @L); +----------------------------------------------------------------------------+ | JSON_MERGE_PRESERVE(@k, @m, @j, @L) | +----------------------------------------------------------------------------+ | {"1": "math", "key": "value", "case": "[2,true,NULL]", "country": "China"} | +----------------------------------------------------------------------------+ 1 row in set (0.00 sec)
使用
mysql> SELECT CHARSET(@j), COLLATION(@j); +-------------+---------------+ | CHARSET(@j) | COLLATION(@j) | +-------------+---------------+ | utf8mb4 | utf8mb4_bin | +-------------+---------------+ 1 row in set (0.01 sec)
由于
mysql> SELECT JSON_ARRAY('x')=JSON_ARRAY('X'); +---------------------------------+ | JSON_ARRAY('x')=JSON_ARRAY('X') | +---------------------------------+ | 0 | +---------------------------------+ 1 row in set (0.00 sec)
对于
mysql> SELECT JSON_VALID('null'), JSON_VALID(null); +--------------------+------------------+ | JSON_VALID('null') | JSON_VALID(null) | +--------------------+------------------+ | 1 | NULL | +--------------------+------------------+ 1 row in set (0.04 sec) mysql> SELECT JSON_VALID('Null'), JSON_VALID(NULL); +--------------------+------------------+ | JSON_VALID('Null') | JSON_VALID(NULL) | +--------------------+------------------+ | 0 | NULL | +--------------------+------------------+ 1 row in set (0.00 sec)
MySQL 中的
mysql> SELECT CAST('null' AS JSON); +----------------------+ | CAST('null' AS JSON) | +----------------------+ | null | +----------------------+ 1 row in set (0.01 sec)
如果不是小写的
mysql> SELECT CAST('NULL' AS JSON); mysql> SELECT CAST('Null' AS JSON); mysql> SELECT CAST('NulL' AS JSON); ERROR 3141 (22032): Invalid JSON text in argument 1 to function cast_as_json: "Invalid value." at position 0.
对比之下,
mysql> SELECT ISNULL(null), ISNULL(Null), ISNULL(NULL); +--------------+--------------+--------------+ | ISNULL(null) | ISNULL(Null) | ISNULL(NULL) | +--------------+--------------+--------------+ | 1 | 1 | 1 | +--------------+--------------+--------------+ 1 row in set (0.00 sec)
有时在 JSON 文档中有必要插入一些引号(双引号"和单引号'). 此时要用转义符\. 即 \" 表示字符串中的双引号.
切换到
mysql> use test_students; Database changed mysql> select * from my_table; +----+--------------------------------------+ | id | json_data | +----+--------------------------------------+ | 1 | {"key1": "value1", "key2": "value2"} | | 2 | ["hello", 0, true, null, false] | | 3 | [null, 12, false, null, "hello"] | +----+--------------------------------------+ 3 rows in set (0.00 sec) mysql> INSERT INTO my_table VALUES -> (4, JSON_OBJECT("Sowya", "Sowya is a computing software that runs on \"Windows\" and \"Linux\".")); Query OK, 1 row affected (0.00 sec) mysql> select * from my_table; +----+------------------------------------------------------------------------------------+ | id | json_data | +----+------------------------------------------------------------------------------------+ | 1 | {"key1": "value1", "key2": "value2"} | | 2 | ["hello", 0, true, null, false] | | 3 | [null, 12, false, null, "hello"] | | 4 | {"Sowya": "Sowya is a computing software that runs on \"Windows\" and \"Linux\"."} | +----+------------------------------------------------------------------------------------+ 4 rows in set (0.00 sec)