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)