Mysql的JSON函数
Mysql的版本为5.7。
12.18.1 JSON 函数参考
表 12.22 JSON 函数
姓名 | 描述 | 函数分类。 | 版本 |
---|---|---|---|
-> | 从 JSON 列返回右侧路径评估后的值;相当于 JSON_EXTRACT() 。 column->path | 搜索 | 从5.7.9 |
->> | 评估路径并取消引用结果后从 JSON 列返回值;相当于 JSON_UNQUOTE(JSON_EXTRACT()) 。 column->>path | 搜索 | 从5.7.13 |
JSON_APPEND() | 修改 | 弃用于5.7.9 | |
JSON_ARRAY() | 创建 JSON 数组。json_array('a',1); -> ["a", 1] | 创建 | |
JSON_ARRAY_APPEND() | 将数据附加到 JSON 文档。JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...) | 修改 | |
JSON_ARRAY_INSERT() | 插入 JSON 数组。 JSON_ARRAY_INSERT(json_doc, path, val[, path, val] ...) | 修改 | |
JSON_CONTAINS() | JSON 文档是否在路径中包含特定对象. JSON_CONTAINS(target, candidate[, path]) | 搜索 | |
JSON_CONTAINS_PATH() | JSON 文档是否包含路径中的任何数据. JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] ...) | 搜索 | |
JSON_DEPTH() | JSON 文档的最大深度. JSON_DEPTH(json_doc) | 查属性 | |
JSON_EXTRACT() | 从 JSON 文档返回数据,与 -> 是同义词. JSON_EXTRACT(json_doc, path[, path] ...) | 搜索 | |
JSON_INSERT() | 将数据插入 JSON 文档。 JSON_INSERT(json_doc, path, val[, path, val] ...) | 修改 | |
JSON_KEYS() | JSON 文档中的键数组. JSON_KEYS(json_doc[, path]) | 查属性 | |
JSON_LENGTH() | JSON 文档中的元素数. JSON_LENGTH(json_doc[, path]) | 查属性 | |
JSON_MERGE() | JSON_MERGE_PRESERVE() 代替。 JSON_MERGE(json_doc, json_doc[, json_doc] ...) | 修改 | 弃用于5.7.22 |
JSON_MERGE_PATCH() | 合并 JSON 文档,替换重复键的值。 JSON_MERGE_PATCH(json_doc, json_doc[, json_doc] ...) | 修改 | 从5.7.22 |
JSON_MERGE_PRESERVE() | 合并 JSON 文档,保留重复键。 JSON_MERGE_PRESERVE(json_doc, json_doc[, json_doc] ...) | 修改 | 从5.7.22 |
JSON_OBJECT() | 创建 JSON 对象。json_object('a',1); -> {"a": 1} | 创建 | |
JSON_PRETTY() | 以人类可读的格式打印 JSON 文档. JSON_PRETTY(json_val) | 格式化 | 从5.7.22 |
JSON_QUOTE() | 在 JSON 文档的两端增加引号并将内部的引号转义. JSON_QUOTE(string) | 创建 | |
JSON_REMOVE() | 从 JSON 文档中删除数据。 JSON_REMOVE(json_doc, path[, path] ...) | 修改 | |
JSON_REPLACE() | 替换 JSON 文档中的值. JSON_REPLACE(json_doc, path, val[, path, val] ...) | 修改 | |
JSON_SEARCH() | JSON 文档中值的路径. JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] ...]) | 搜索 | |
JSON_SET() | 将数据插入 JSON 文档. JSON_SET(json_doc, path, val[, path, val] ...) | 修改 | |
JSON_STORAGE_SIZE() | 用于存储 JSON 文档的二进制表示的空间. JSON_STORAGE_SIZE(json_val) | 查属性 | 从5.7.22 |
JSON_TYPE() | JSON 值的类型. JSON_TYPE(json_val) | 查属性 | |
JSON_UNQUOTE() | 去掉 JSON 值的引号. JSON_UNQUOTE(json_val) | 修改 | |
JSON_VALID() | JSON值是否有效. JSON_VALID(val) | 查属性 |
MySQL 5.7.22 及更高版本支持两个聚合 JSON 函数 JSON_ARRAYAGG()
和 JSON_OBJECTAGG()
. 有关这些的描述,请参见 第 12.20 节,“聚合函数”。
同样从 MySQL 5.7.22 开始:
JSON_PRETTY()
使用该函数 可以获得易读格式的 JSON 值的 “漂亮打印” 。- 您可以看到给定的 JSON 值占用了多少存储空间
JSON_STORAGE_SIZE()
。
有关这两个函数的完整描述,请参阅 第 12.18.6 节,“JSON 实用函数”。
12.18.2 创建 JSON 值的函数
本节中列出的函数由组件元素组成 JSON 值。
12.18.2.1 JSON_ARRAY([val[, val] ...])
评估一个(可能为空的)值列表并返回一个包含这些值的 JSON 数组。
mysql> SELECT JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME());
+---------------------------------------------+
| JSON_ARRAY(1, "abc", NULL, TRUE, CURTIME()) |
+---------------------------------------------+
| [1, "abc", null, true, "11:30:24.000000"] |
+---------------------------------------------+
12.18.2.2 JSON_OBJECT([key, val[, key, val] ...])
评估一个(可能为空的)键值对列表并返回一个包含这些对的 JSON 对象。
如果任何键名称为NULL
或参数数量为奇数, 则会发生错误。
mysql> SELECT JSON_OBJECT('id', 87, 'name', 'carrot');
+-----------------------------------------+
| JSON_OBJECT('id', 87, 'name', 'carrot') |
+-----------------------------------------+
| {"id": 87, "name": "carrot"} |
+-----------------------------------------+
12.18.2.3 JSON_QUOTE(string)
通过用双引号字符包装字符串并转义内部引号和其他字符,将字符串引用为 JSON 值,然后将结果作为 utf8mb4
字符串返回。如果参数是 NULL
则返回 NULL
。
此函数通常用于生成有效的 JSON 字符串文字以包含在 JSON 文档中。
根据表 12.23,“JSON_UNQUOTE() 特殊字符转义序列” 中显示的转义序列,某些特殊字符使用反斜杠进行转义 。
mysql> SELECT JSON_QUOTE('null'), JSON_QUOTE('"null"');
+--------------------+----------------------+
| JSON_QUOTE('null') | JSON_QUOTE('"null"') |
+--------------------+----------------------+
| "null" | "\"null\"" |
+--------------------+----------------------+
mysql> SELECT JSON_QUOTE('[1, 2, 3]');
+-------------------------+
| JSON_QUOTE('[1, 2, 3]') |
+-------------------------+
| "[1, 2, 3]" |
+-------------------------+
您还可以通过使用 CAST(*
value* AS JSON)
将其他类型的值转换为JSON
的类型来获取 JSON 值;有关更多信息, 请参阅 JSON 和非 JSON 值之间的转换。
有两个生成 JSON 值的聚合函数可用(MySQL 5.7.22 和更高版本)。 JSON_ARRAYAGG()
将结果集作为单个 JSON 数组返回,JSON_OBJECTAGG()
将结果集作为单个 JSON 对象返回。有关更多信息,请参阅 第 12.20 节,“聚合函数”。
12.18.3 搜索 JSON 值的函数
- JSON_CONTAINS(target, candidate[, path])
- JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] …)
- JSON_EXTRACT(json_doc, path[, path] …)
- column->path
- column->>path
- JSON_KEYS(json_doc[, path])
- JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] …])
本节中的函数对 JSON 值执行搜索操作以从中提取数据,报告数据是否存在于其中的某个位置,或者报告其中数据的路径。
12.18.3.1 JSON_CONTAINS(target, candidate[, path])
通过返回 1 或 0 来指示给定的 candidate
JSON 文档是否包含在*target
* JSON 文档中,或者是否在目标内的特定路径中找到候选对象(如果 提供了*path
*参数)。
- 如果任何参数是
NULL
,或者路径参数标识的文档不存在,则返回NULL
。 - 如果*
target
*或 *candidate
不是有效的 JSON 文档,或者path
*参数不是有效的路径表达式或包含*
或**
通配符 ,则会发生错误 。
要仅检查路径中是否存在任何数据,请改用 JSON_CONTAINS_PATH()
。
以下规则定义了“包含”的含义:
- 当且仅当它们可比较且相等时,候选标量包含在目标标量中。如果两个标量值具有相同的
JSON_TYPE()
类型,则它们是可比较的,有一个例外是INTEGER
和DECIMAL
也可以相互比较。 - 当且仅当候选数组中的每个元素都包含在目标的某个元素中时,则被判定为“包含”(候选数组包含在目标数组中)。
- 当且仅当候选元素包含在目标数组的某个元素中时,则被判定为“包含”(候选非数组元素包含在目标数组中)。
- 候选对象包含在目标对象中当且仅当对于候选对象中的每个键在目标中存在同名键并且与候选键关联的值包含在与目标键关联的值中。
否则,候选值不包含在目标文档中。
mysql> SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}';
mysql> SET @j2 = '1';
mysql> SELECT JSON_CONTAINS(@j, @j2, '$.a');
+-------------------------------+
| JSON_CONTAINS(@j, @j2, '$.a') |
+-------------------------------+
| 1 |
+-------------------------------+
mysql> SELECT JSON_CONTAINS(@j, @j2, '$.b');
+-------------------------------+
| JSON_CONTAINS(@j, @j2, '$.b') |
+-------------------------------+
| 0 |
+-------------------------------+
mysql> SET @j2 = '{"d": 4}';
mysql> SELECT JSON_CONTAINS(@j, @j2, '$.a');
+-------------------------------+
| JSON_CONTAINS(@j, @j2, '$.a') |
+-------------------------------+
| 0 |
+-------------------------------+
mysql> SELECT JSON_CONTAINS(@j, @j2, '$.c');
+-------------------------------+
| JSON_CONTAINS(@j, @j2, '$.c') |
+-------------------------------+
| 1 |
+-------------------------------+
12.18.3.2 JSON_CONTAINS_PATH(json_doc, one_or_all, path[, path] ...)
返回 0 或 1 以指示 JSON 文档是否包含给定路径或路径中的数据。
- 如果任何参数是
NULL
则返回NULL
。 - 如果参数*
json_doc
不是有效的 JSON 文档,任何path
* 参数不是有效的路径表达式,或者 *one_or_all
*不是'one'
或'all'
,则会发生错误。
要检查路径中的特定值,请改用 JSON_CONTAINS()
。
如果文档中不存在指定的路径,则返回值为 0。否则,返回值取决于 *one_or_all
*参数:
'one'
: 如果文档中至少存在一个路径,则为 1,否则为 0。'all'
: 如果所有路径都存在于文档中,则为 1,否则为 0。
mysql> SET @j = '{"a": 1, "b": 2, "c": {"d": 4}}';
mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e');
+---------------------------------------------+
| JSON_CONTAINS_PATH(@j, 'one', '$.a', '$.e') |
+---------------------------------------------+
| 1 |
+---------------------------------------------+
mysql> SELECT JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e');
+---------------------------------------------+
| JSON_CONTAINS_PATH(@j, 'all', '$.a', '$.e') |
+---------------------------------------------+
| 0 |
+---------------------------------------------+
mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.c.d');
+----------------------------------------+
| JSON_CONTAINS_PATH(@j, 'one', '$.c.d') |
+----------------------------------------+
| 1 |
+----------------------------------------+
mysql> SELECT JSON_CONTAINS_PATH(@j, 'one', '$.a.d');
+----------------------------------------+
| JSON_CONTAINS_PATH(@j, 'one', '$.a.d') |
+----------------------------------------+
| 0 |
+----------------------------------------+
12.18.3.3 JSON_EXTRACT(json_doc, path[, path] ...)
从 JSON 文档中抽取数据,从与*path
* 参数匹配的文档部分中抽取。
- 如果任何参数是
NULL
或没有路径在文档中定位一个值,则返回NULL
。 - 如果*
json_doc
参数不是有效的 JSON 文档或任何path
*参数不是有效的路径表达式, 则会发生错误 。
返回值由与 *path
*参数匹配的所有值组成。如果这些参数有可能返回多个值,则匹配的值将按照与生成它们的路径相对应的顺序自动包装为数组。否则,返回值是单个匹配值。
mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]');
+--------------------------------------------+
| JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]') |
+--------------------------------------------+
| 20 |
+--------------------------------------------+
mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]');
+----------------------------------------------------+
| JSON_EXTRACT('[10, 20, [30, 40]]', '$[1]', '$[0]') |
+----------------------------------------------------+
| [20, 10] |
+----------------------------------------------------+
mysql> SELECT JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]');
+-----------------------------------------------+
| JSON_EXTRACT('[10, 20, [30, 40]]', '$[2][*]') |
+-----------------------------------------------+
| [30, 40] |
+-----------------------------------------------+
12.18.3.3 column->path
在 MySQL 5.7.9 及更高版本中, ->
运算符在与两个参数一起使用时充当函数JSON_EXTRACT()
的别名,左侧是列标识符,右侧是 JSON 路径(字符串文字),根据 JSON 文档(列值)。您可以使用此类表达式代替列引用,只要它们出现在 SQL 语句中。
此处显示的两个SELECT
语句产生相同的输出:
mysql> SELECT c, JSON_EXTRACT(c, "$.id"), g
> FROM jemp
> WHERE JSON_EXTRACT(c, "$.id") > 1
> ORDER BY JSON_EXTRACT(c, "$.name");
+-------------------------------+-----------+------+
| c | c->"$.id" | g |
+-------------------------------+-----------+------+
| {"id": "3", "name": "Barney"} | "3" | 3 |
| {"id": "4", "name": "Betty"} | "4" | 4 |
| {"id": "2", "name": "Wilma"} | "2" | 2 |
+-------------------------------+-----------+------+
3 rows in set (0.00 sec)
mysql> SELECT c, c->"$.id", g
> FROM jemp
> WHERE c->"$.id" > 1
> ORDER BY c->"$.name";
+-------------------------------+-----------+------+
| c | c->"$.id" | g |
+-------------------------------+-----------+------+
| {"id": "3", "name": "Barney"} | "3" | 3 |
| {"id": "4", "name": "Betty"} | "4" | 4 |
| {"id": "2", "name": "Wilma"} | "2" | 2 |
+-------------------------------+-----------+------+
3 rows in set (0.00 sec)
此功能不限于 SELECT
,如下所示:
mysql> ALTER TABLE jemp ADD COLUMN n INT;
Query OK, 0 rows affected (0.68 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> UPDATE jemp SET n=1 WHERE c->"$.id" = "4";
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT c, c->"$.id", g, n
> FROM jemp
> WHERE JSON_EXTRACT(c, "$.id") > 1
> ORDER BY c->"$.name";
+-------------------------------+-----------+------+------+
| c | c->"$.id" | g | n |
+-------------------------------+-----------+------+------+
| {"id": "3", "name": "Barney"} | "3" | 3 | NULL |
| {"id": "4", "name": "Betty"} | "4" | 4 | 1 |
| {"id": "2", "name": "Wilma"} | "2" | 2 | NULL |
+-------------------------------+-----------+------+------+
3 rows in set (0.00 sec)
mysql> DELETE FROM jemp WHERE c->"$.id" = "4";
Query OK, 1 row affected (0.04 sec)
mysql> SELECT c, c->"$.id", g, n
> FROM jemp
> WHERE JSON_EXTRACT(c, "$.id") > 1
> ORDER BY c->"$.name";
+-------------------------------+-----------+------+------+
| c | c->"$.id" | g | n |
+-------------------------------+-----------+------+------+
| {"id": "3", "name": "Barney"} | "3" | 3 | NULL |
| {"id": "2", "name": "Wilma"} | "2" | 2 | NULL |
+-------------------------------+-----------+------+------+
2 rows in set (0.00 sec)
(有关用于创建和填充刚刚显示的表的语句, 请参阅索引生成的列以提供 JSON 列索引。)
这也适用于 JSON 数组值,如下所示:
mysql> CREATE TABLE tj10 (a JSON, b INT);
Query OK, 0 rows affected (0.26 sec)
mysql> INSERT INTO tj10
> VALUES ("[3,10,5,17,44]", 33), ("[3,10,5,17,[22,44,66]]", 0);
Query OK, 1 row affected (0.04 sec)
mysql> SELECT a->"$[4]" FROM tj10;
+--------------+
| a->"$[4]" |
+--------------+
| 44 |
| [22, 44, 66] |
+--------------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM tj10 WHERE a->"$[0]" = 3;
+------------------------------+------+
| a | b |
+------------------------------+------+
| [3, 10, 5, 17, 44] | 33 |
| [3, 10, 5, 17, [22, 44, 66]] | 0 |
+------------------------------+------+
2 rows in set (0.00 sec)
支持嵌套数组。如果在目标 JSON 文档中找不到匹配的键,则表达式 ->
的计算结果为NULL
,如下所示:
mysql> SELECT * FROM tj10 WHERE a->"$[4][1]" IS NOT NULL;
+------------------------------+------+
| a | b |
+------------------------------+------+
| [3, 10, 5, 17, [22, 44, 66]] | 0 |
+------------------------------+------+
mysql> SELECT a->"$[4][1]" FROM tj10;
+--------------+
| a->"$[4][1]" |
+--------------+
| NULL |
| 44 |
+--------------+
2 rows in set (0.00 sec)
这与使用JSON_EXTRACT()
时在这种情况下看到的行为相同:
mysql> SELECT JSON_EXTRACT(a, "$[4][1]") FROM tj10;
+----------------------------+
| JSON_EXTRACT(a, "$[4][1]") |
+----------------------------+
| NULL |
| 44 |
+----------------------------+
2 rows in set (0.00 sec)
->
不支持对变量直接使用,也不支持对字符串直接使用,如以下的用法会报错:
mysql> select '{"a":"b"}' -> '$.a';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-> '$.a'' at line 1
mysql> set @jj = '{"name":"ziv"}';
Query OK, 0 rows affected (0.00 sec)
mysql> select @jj -> '$.name';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-> '$.name'' at line 1
12.18.3.4 column->>path
这是 MySQL 5.7.13 及更高版本中提供的改进的、取消引号的提取运算符。->
运算符只是简单地提取一个值,而 ->>
运算符额外取消提取结果的引号。换句话说,给定一个 JSON
列值 *column
*和一个路径表达式 path
(字符串文字),以下三个表达式返回相同的值:
JSON_UNQUOTE(
JSON_EXTRACT(column, path) )
JSON_UNQUOTE(column
->
path)
column->>path
->>
运算符可以在任何允许 JSON_UNQUOTE(JSON_EXTRACT())
的地方使用。这包括(但不限于) SELECT
列表、WHERE
、HAVING
、 ORDER BY
和 GROUP BY
子句。
接下来的几条语句演示了一些 ->>
运算符与mysql客户端中其他表达式的等价关系:
mysql> SELECT * FROM jemp WHERE g > 2;
+-------------------------------+------+
| c | g |
+-------------------------------+------+
| {"id": "3", "name": "Barney"} | 3 |
| {"id": "4", "name": "Betty"} | 4 |
+-------------------------------+------+
2 rows in set (0.01 sec)
mysql> SELECT c->'$.name' AS name
-> FROM jemp WHERE g > 2;
+----------+
| name |
+----------+
| "Barney" |
| "Betty" |
+----------+
2 rows in set (0.00 sec)
mysql> SELECT JSON_UNQUOTE(c->'$.name') AS name
-> FROM jemp WHERE g > 2;
+--------+
| name |
+--------+
| Barney |
| Betty |
+--------+
2 rows in set (0.00 sec)
mysql> SELECT c->>'$.name' AS name
-> FROM jemp WHERE g > 2;
+--------+
| name |
+--------+
| Barney |
| Betty |
+--------+
2 rows in set (0.00 sec)
此运算符也能与 JSON 数组一起使用,示例省略了。
12.18.3.5 JSON_KEYS(json_doc[, path])
将 JSON 对象的顶级键作为 JSON 数组返回,或者,如果给定参数 path
,则返回所选路径中的顶级键。
- 如果任何参数是
NULL
,或者该*json_doc
参数不是对象,或者path
*(如果给定)不定位到任何对象,则返回NULL
。 - *
json_doc
如果参数不是有效的 JSON 文档或path
*参数不是有效的路径表达式或包含*
或**
通配符, 则会发生错误 。
如果所选对象为空,则结果数组为空。如果顶级值具有嵌套的子对象,则返回值不包括来自这些子对象的键。
mysql> SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}');
+---------------------------------------+
| JSON_KEYS('{"a": 1, "b": {"c": 30}}') |
+---------------------------------------+
| ["a", "b"] |
+---------------------------------------+
mysql> SELECT JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b');
+----------------------------------------------+
| JSON_KEYS('{"a": 1, "b": {"c": 30}}', '$.b') |
+----------------------------------------------+
| ["c"] |
+----------------------------------------------+
12.18.3.6 JSON_SEARCH(json_doc, one_or_all, search_str[, escape_char[, path] ...\])
返回 JSON 文档中给定字符串的路径。
- 如果
json_doc
、search_str
或*path
* 参数中的任何一个是NULL
,或者文档中不存在path
,或未找到search_str
,则返回NULL
。 - 如果*
json_doc
参数不是有效的 JSON 文档、任何path
* 参数不是有效的路径表达式、 *one_or_all
*不是'one'
or'all'
或 *escape_char
*不是常量表达式,则会发生错误。
该*one_or_all
*参数对搜索的影响如下:
'one'
: 搜索在第一次匹配后终止并返回一个路径字符串。但并未定义优先匹配哪个。'all'
:搜索返回所有匹配的路径字符串,这样不包括重复的路径。如果有多个字符串,它们会自动包装为一个数组,但并为定义数组元素的顺序。
在*search_str
*搜索字符串参数中,%
和 _
字符与LIKE
运算符一样工作:%
匹配任意数量的字符(包括零个字符),并且 _
只匹配一个字符。
要在搜索字符串中指定文字%
或 _
字符,请在其前面加上转义字符。默认情况下是 \
,(如果 *escape_char
*参数丢失或 NULL
), 否则 *escape_char
*必须是一个空或单字符常量。
有关匹配和转义字符行为的更多信息,请参阅 第 12.8.1 节,“字符串比较函数和运算符” 中 LIKE
的描述。对于转义字符处理,与 LIKE
行为的不同之处在于 JSON_SEARCH()
的转义字符必须在编译时计算为常量,而不仅仅是在执行时。例如,如果 JSON_SEARCH()
在预定义语句中使用并且使用 escape_char
参数提供?
参数,则参数值在执行时可能是常量,但在编译时不是。(–译者注:没看明白)
search_str
和 path
总是以 utf8mb4 字符串的形式插入,无论它们的实际编码如何。这是一个已知问题,已在 MySQL 8.0 中修复(错误 #32449181)。
mysql> SET @j = '["abc", [{"k": "10"}, "def"], {"x":"abc"}, {"y":"bcd"}]';
mysql> SELECT JSON_SEARCH(@j, 'one', 'abc');
+-------------------------------+
| JSON_SEARCH(@j, 'one', 'abc') |
+-------------------------------+
| "$[0]" |
+-------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', 'abc');
+-------------------------------+
| JSON_SEARCH(@j, 'all', 'abc') |
+-------------------------------+
| ["$[0]", "$[2].x"] |
+-------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', 'ghi');
+-------------------------------+
| JSON_SEARCH(@j, 'all', 'ghi') |
+-------------------------------+
| NULL |
+-------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '10');
+------------------------------+
| JSON_SEARCH(@j, 'all', '10') |
+------------------------------+
| "$[1][0].k" |
+------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$');
+-----------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$') |
+-----------------------------------------+
| "$[1][0].k" |
+-----------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[*]');
+--------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$[*]') |
+--------------------------------------------+
| "$[1][0].k" |
+--------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$**.k');
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$**.k') |
+---------------------------------------------+
| "$[1][0].k" |
+---------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[*][0].k');
+-------------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$[*][0].k') |
+-------------------------------------------------+
| "$[1][0].k" |
+-------------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[1]');
+--------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$[1]') |
+--------------------------------------------+
| "$[1][0].k" |
+--------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '10', NULL, '$[1][0]');
+-----------------------------------------------+
| JSON_SEARCH(@j, 'all', '10', NULL, '$[1][0]') |
+-----------------------------------------------+
| "$[1][0].k" |
+-----------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', 'abc', NULL, '$[2]');
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', 'abc', NULL, '$[2]') |
+---------------------------------------------+
| "$[2].x" |
+---------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '%a%');
+-------------------------------+
| JSON_SEARCH(@j, 'all', '%a%') |
+-------------------------------+
| ["$[0]", "$[2].x"] |
+-------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '%b%');
+-------------------------------+
| JSON_SEARCH(@j, 'all', '%b%') |
+-------------------------------+
| ["$[0]", "$[2].x", "$[3].y"] |
+-------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[0]');
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', NULL, '$[0]') |
+---------------------------------------------+
| "$[0]" |
+---------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[2]');
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', NULL, '$[2]') |
+---------------------------------------------+
| "$[2].x" |
+---------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', NULL, '$[1]');
+---------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', NULL, '$[1]') |
+---------------------------------------------+
| NULL |
+---------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[1]');
+-------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', '', '$[1]') |
+-------------------------------------------+
| NULL |
+-------------------------------------------+
mysql> SELECT JSON_SEARCH(@j, 'all', '%b%', '', '$[3]');
+-------------------------------------------+
| JSON_SEARCH(@j, 'all', '%b%', '', '$[3]') |
+-------------------------------------------+
| "$[3].y" |
+-------------------------------------------+
12.18.4 修改 JSON 值的函数
- JSON_APPEND(json_doc, path, val[, path, val] …)
- JSON_ARRAY_APPEND(json_doc, path, val[, path, val] …)
- JSON_ARRAY_INSERT(json_doc, path, val[, path, val] …)
- JSON_INSERT(json_doc, path, val[, path, val] …)
- JSON_MERGE(json_doc, json_doc[, json_doc] …)
- JSON_MERGE_PATCH(json_doc, json_doc[, json_doc] …)
- JSON_MERGE_PRESERVE(json_doc, json_doc[, json_doc] …)
- JSON_REMOVE(json_doc, path[, path] …)
- JSON_REPLACE(json_doc, path, val[, path, val] …)
- JSON_SET(json_doc, path, val[, path, val] …)
- JSON_UNQUOTE(json_val)
12.18.4.1 JSON_APPEND(json_doc, path, val[, path, val] ...)
JSON_APPEND(json_doc, path, val[, path, val] ...)
已废弃(从5.7.9,计划于8.0删除)。将值附加到 JSON 文档中指定数组的末尾并返回结果。使用JSON_ARRAY_APPEND
代替。
12.18.4.2 JSON_ARRAY_APPEND(json_doc, path, val[, path, val] ...)
将值追加到 JSON 文档中指定数组的末尾并返回结果。
-
如果任何参数是
NULL
则返回NULL
。 -
如果参数*
json_doc
不是有效的 JSON 文档或任何path
*参数不是有效的路径表达式或包含*
或**
通配符, 则会发生错误 。
路径值对从左到右进行评估。通过评估一对生成的文档成为评估下一对的新值。
-
如果路径对应的不是数组,而是标量或对象值,则该值将被包装在一个新数组中,并将新值添加到该数组中。
-
路径未标识 JSON 文档中任何值的对将被忽略。
mysql> SET @j = '["a", ["b", "c"], "d"]';
mysql> SELECT JSON_ARRAY_APPEND(@j, '$[1]', 1);
+----------------------------------+
| JSON_ARRAY_APPEND(@j, '$[1]', 1) |
+----------------------------------+
| ["a", ["b", "c", 1], "d"] |
+----------------------------------+
mysql> SELECT JSON_ARRAY_APPEND(@j, '$[0]', 2);
+----------------------------------+
| JSON_ARRAY_APPEND(@j, '$[0]', 2) |
+----------------------------------+
| [["a", 2], ["b", "c"], "d"] |
+----------------------------------+
mysql> SELECT JSON_ARRAY_APPEND(@j, '$[1][0]', 3);
+-------------------------------------+
| JSON_ARRAY_APPEND(@j, '$[1][0]', 3) |
+-------------------------------------+
| ["a", [["b", 3], "c"], "d"] |
+-------------------------------------+
mysql> SET @j = '{"a": 1, "b": [2, 3], "c": 4}';
mysql> SELECT JSON_ARRAY_APPEND(@j, '$.b', 'x');
+------------------------------------+
| JSON_ARRAY_APPEND(@j, '$.b', 'x') |
+------------------------------------+
| {"a": 1, "b": [2, 3, "x"], "c": 4} |
+------------------------------------+
mysql> SELECT JSON_ARRAY_APPEND(@j, '$.c', 'y');
+--------------------------------------+
| JSON_ARRAY_APPEND(@j, '$.c', 'y') |
+--------------------------------------+
| {"a": 1, "b": [2, 3], "c": [4, "y"]} |
+--------------------------------------+
mysql> SET @j = '{"a": 1}';
mysql> SELECT JSON_ARRAY_APPEND(@j, '$', 'z');
+---------------------------------+
| JSON_ARRAY_APPEND(@j, '$', 'z') |
+---------------------------------+
| [{"a": 1}, "z"] |
+---------------------------------+
12.18.4.3 JSON_ARRAY_INSERT(json_doc, path, val[, path, val] ...)
更新 JSON 文档,将val插入数组并返回修改后的文档。
- 如果任何参数是
NULL
则返回NULL
。 - 如果 *
json_doc
参数不是有效的 JSON 文档或任何path
*参数不是有效的路径表达式或包含*
或**
通配符或不以数组元素标识符结尾,则会发生错误。
路径值对从左到右进行评估。通过评估一对生成的文档成为评估下一对的新值。
-
路径未标识 JSON 文档中的任何数组的对将被忽略。
-
如果路径标识了一个数组元素,则在该元素位置插入相应的值,将任何后续值向右移动。如果路径标识了数组末尾之后的数组位置(>=末尾),则将值插入到数组末尾。
mysql> SET @j = '["a", {"b": [1, 2]}, [3, 4]]';
mysql> SELECT JSON_ARRAY_INSERT(@j, '$[1]', 'x');
+------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[1]', 'x') |
+------------------------------------+
| ["a", "x", {"b": [1, 2]}, [3, 4]] |
+------------------------------------+
mysql> SELECT JSON_ARRAY_INSERT(@j, '$[100]', 'x');
+--------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[100]', 'x') |
+--------------------------------------+
| ["a", {"b": [1, 2]}, [3, 4], "x"] |
+--------------------------------------+
mysql> SELECT JSON_ARRAY_INSERT(@j, '$[1].b[0]', 'x');
+-----------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[1].b[0]', 'x') |
+-----------------------------------------+
| ["a", {"b": ["x", 1, 2]}, [3, 4]] |
+-----------------------------------------+
mysql> SELECT JSON_ARRAY_INSERT(@j, '$[2][1]', 'y');
+---------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[2][1]', 'y') |
+---------------------------------------+
| ["a", {"b": [1, 2]}, [3, "y", 4]] |
+---------------------------------------+
mysql> SELECT JSON_ARRAY_INSERT(@j, '$[0]', 'x', '$[2][1]', 'y');
+----------------------------------------------------+
| JSON_ARRAY_INSERT(@j, '$[0]', 'x', '$[2][1]', 'y') |
+----------------------------------------------------+
| ["x", "a", {"b": [1, 2]}, [3, 4]] |
+----------------------------------------------------+
较早的修改会影响数组中以下元素的位置,因此同一 JSON_ARRAY_INSERT()
调用中的后续路径应考虑到这一点。在最后一个示例中,第二个路径不插入任何内容,因为在第一个插入之后该路径不再匹配任何内容。
12.18.4.4 JSON_INSERT(json_doc, path, val[, path, val] ...)
将数据插入 JSON 文档并返回结果。
- 如果任何参数是
NULL
则返回NULL
。 - 如果参数*
json_doc
不是有效的 JSON 文档或任何path
*参数不是有效的路径表达式或包含*
或**
通配符, 则会发生错误 。
路径值对从左到右进行评估。通过评估一对生成的文档成为评估下一对的新值。
如果待插入的位置上已经存在值了,则参数中的path-value对将被忽略,并且不会覆盖现有文档值。如果路径标识以下类型的值之一,则文档中不存在路径的path-value对将被添加到文档中:
- 现有对象中不存在的成员。该成员被添加到对象并与新值相关联。
- 超过现有数组末尾的位置。使用新值扩展数组。如果现有值不是数组,则将其自动包装为数组,然后使用新值进行扩展。
否则,文档中不存在路径的path-value对将被忽略且无效。
有关 JSON_INSERT()
、 JSON_REPLACE()
和JSON_SET()
的比较, 请参阅 JSON_SET()
的讨论。
mysql> SET @j = '{ "a": 1, "b": [2, 3]}';
mysql> SELECT JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]');
+----------------------------------------------------+
| JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]') |
+----------------------------------------------------+
| {"a": 1, "b": [2, 3], "c": "[true, false]"} |
+----------------------------------------------------+
结果中列出的第三个也是最后一个值是带引号的字符串,而不是像第二个那样的数组(输出中没有引用);没有将值转换为 JSON 类型。要将数组作为数组插入,您必须显式执行此类转换,如下所示:
mysql> SELECT JSON_INSERT(@j, '$.a', 10, '$.c', CAST('[true, false]' AS JSON));
+------------------------------------------------------------------+
| JSON_INSERT(@j, '$.a', 10, '$.c', CAST('[true, false]' AS JSON)) |
+------------------------------------------------------------------+
| {"a": 1, "b": [2, 3], "c": [true, false]} |
+------------------------------------------------------------------+
1 row in set (0.00 sec)
12.18.4.5 JSON_MERGE(json_doc, json_doc[, json_doc] ...)
合并两个或多个 JSON 文档。JSON_MERGE_PRESERVE()
的同义词; 在 MySQL 5.7.22 中已弃用,并在未来版本中删除。
12.18.4.6 JSON_MERGE_PATCH(json_doc, json_doc[, json_doc] ...)
执行两个或多个 JSON 文档的 RFC 7396兼容合并并返回合并结果,而不保留具有重复键的成员。如果作为参数传递给此函数的至少一个文档无效,则会引发错误。从5.7.22新增的方法。
说明
有关此函数和
JSON_MERGE_PRESERVE()
之间差异的说明和示例,请参阅 JSON_MERGE_PATCH() 与 JSON_MERGE_PRESERVE() 的比较。
JSON_MERGE_PATCH()
执行如下合并:
- 如果第一个参数不是对象,则合并的结果与将空对象与第二个参数合并的结果相同。
- 如果第二个参数不是对象,则合并的结果是第二个参数。
- 如果两个参数都是对象,则合并的结果是具有以下成员的对象:
- 第一个对象的所有成员,在第二个对象中没有具有相同键的对应成员。
- 第二个对象的所有成员,在第一个对象中没有对应的键,并且其值不是 JSON
null
字面量。 - 所有成员的键同时存在于第一个和第二个对象中,并且其在第二个对象中的值不是 JSON
null
字面量。这些成员的值是递归合并第一个对象中的值与第二个对象中的值的结果。
有关其他信息,请参阅 JSON 值的规范化、合并和自动包装。
mysql> SELECT JSON_MERGE_PATCH('[1, 2]', '[true, false]');
+---------------------------------------------+
| JSON_MERGE_PATCH('[1, 2]', '[true, false]') |
+---------------------------------------------+
| [true, false] |
+---------------------------------------------+
mysql> SELECT JSON_MERGE_PATCH('{"name": "x"}', '{"id": 47}');
+-------------------------------------------------+
| JSON_MERGE_PATCH('{"name": "x"}', '{"id": 47}') |
+-------------------------------------------------+
| {"id": 47, "name": "x"} |
+-------------------------------------------------+
mysql> SELECT JSON_MERGE_PATCH('1', 'true');
+-------------------------------+
| JSON_MERGE_PATCH('1', 'true') |
+-------------------------------+
| true |
+-------------------------------+
mysql> SELECT JSON_MERGE_PATCH('[1, 2]', '{"id": 47}');
+------------------------------------------+
| JSON_MERGE_PATCH('[1, 2]', '{"id": 47}') |
+------------------------------------------+
| {"id": 47} |
+------------------------------------------+
mysql> SELECT JSON_MERGE_PATCH('{ "a": 1, "b":2 }',
> '{ "a": 3, "c":4 }');
+-----------------------------------------------------------+
| JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }') |
+-----------------------------------------------------------+
| {"a": 3, "b": 2, "c": 4} |
+-----------------------------------------------------------+
mysql> SELECT JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }',
> '{ "a": 5, "d":6 }');
+-------------------------------------------------------------------------------+
| JSON_MERGE_PATCH('{ "a": 1, "b":2 }','{ "a": 3, "c":4 }','{ "a": 5, "d":6 }') |
+-------------------------------------------------------------------------------+
| {"a": 5, "b": 2, "c": 4, "d": 6} |
+-------------------------------------------------------------------------------+
您可以使用此函数通过在第二个参数中指定同一成员的 null
值来删除成员,如下所示:
mysql> SELECT JSON_MERGE_PATCH('{"a":1, "b":2}', '{"b":null}');
+--------------------------------------------------+
| JSON_MERGE_PATCH('{"a":1, "b":2}', '{"b":null}') |
+--------------------------------------------------+
| {"a": 1} |
+--------------------------------------------------+
此示例显示该函数以递归方式运行;也就是说,成员的值不仅限于标量,还可以是 JSON 文档:
mysql> SELECT JSON_MERGE_PATCH('{"a":{"x":1}}', '{"a":{"y":2}}');
+----------------------------------------------------+
| JSON_MERGE_PATCH('{"a":{"x":1}}', '{"a":{"y":2}}') |
+----------------------------------------------------+
| {"a": {"x": 1, "y": 2}} |
+----------------------------------------------------+
JSON_MERGE_PATCH()
在 MySQL 5.7.22 及更高版本中受支持。
12.18.4.7 JSON_MERGE_PRESERVE(json_doc, json_doc[, json_doc] ...)
合并两个或多个 JSON 文档并返回合并结果(尽最大努力保留所有重复的键)。
-
如果任何参数是
NULL
则返回NULL
。 -
如果任何参数不是有效的 JSON 文档,则会发生错误。
合并按照以下规则进行。有关其他信息,请参阅 JSON 值的规范化、合并和自动包装。
- 相邻的多个数组合并为单个数组。
- 相邻的多个对象合并为单个对象。
- 标量值自动包装为数组并合并为数组。
- 通过将对象自动包装为数组并合并两个数组来合并相邻的数组+对象。
mysql> SELECT JSON_MERGE_PRESERVE('[1, 2]', '[true, false]');
+------------------------------------------------+
| JSON_MERGE_PRESERVE('[1, 2]', '[true, false]') |
+------------------------------------------------+
| [1, 2, true, false] |
+------------------------------------------------+
mysql> SELECT JSON_MERGE_PRESERVE('{"name": "x"}', '{"id": 47}');
+----------------------------------------------------+
| JSON_MERGE_PRESERVE('{"name": "x"}', '{"id": 47}') |
+----------------------------------------------------+
| {"id": 47, "name": "x"} |
+----------------------------------------------------+
mysql> SELECT JSON_MERGE_PRESERVE('1', 'true');
+----------------------------------+
| JSON_MERGE_PRESERVE('1', 'true') |
+----------------------------------+
| [1, true] |
+----------------------------------+
mysql> SELECT JSON_MERGE_PRESERVE('[1, 2]', '{"id": 47}');
+---------------------------------------------+
| JSON_MERGE_PRESERVE('[1, 2]', '{"id": 47}') |
+---------------------------------------------+
| [1, 2, {"id": 47}] |
+---------------------------------------------+
mysql> SELECT JSON_MERGE_PRESERVE('{ "a": 1, "b": 2 }',
> '{ "a": 3, "c": 4 }');
+--------------------------------------------------------------+
| JSON_MERGE_PRESERVE('{ "a": 1, "b": 2 }','{ "a": 3, "c":4 }') |
+--------------------------------------------------------------+
| {"a": [1, 3], "b": 2, "c": 4} |
+--------------------------------------------------------------+
mysql> SELECT JSON_MERGE_PRESERVE('{ "a": 1, "b": 2 }','{ "a": 3, "c": 4 }',
> '{ "a": 5, "d": 6 }');
+----------------------------------------------------------------------------------+
| JSON_MERGE_PRESERVE('{ "a": 1, "b": 2 }','{ "a": 3, "c": 4 }','{ "a": 5, "d": 6 }') |
+----------------------------------------------------------------------------------+
| {"a": [1, 3, 5], "b": 2, "c": 4, "d": 6} |
+----------------------------------------------------------------------------------+
此函数在 MySQL 5.7.22 中作为 JSON_MERGE()
的别名,该 JSON_MERGE()
函数现在已弃用,并且可能会在 MySQL 的未来版本中删除。
该函数在重要方面与 JSON_MERGE_PATCH()
类似但又不同 ;有关更多信息,请参阅 JSON_MERGE_PATCH() 与 JSON_MERGE_PRESERVE()的比较。
JSON_MERGE_PATCH() 与 JSON_MERGE_PRESERVE() 的比较
两个不同点:
JSON_MERGE_PATCH()
如果与第二个对象中的键关联的值不是 JSONnull
,则删除第一个对象中具有第二个对象中匹配键的任何成员。- 如果第二个对象的某个成员的键与第一个对象中的成员匹配,则
JSON_MERGE_PATCH()
将第一个对象中 的值 替换为第二个对象中的值,而JSON_MERGE_PRESERVE()
将第二个值 附加到第一个值。
官方说得太绕口,译者翻译成人话:
- PATCH原则:尽量少的保留元素,遇重复则覆盖
- PRESERVE原则:尽量多的保留元素,遇重复则保留两者
此示例比较了将相同的 3 个 JSON 对象(每个对象都有一个匹配的 key "a"
)与以下两个函数中的每一个合并的结果:
mysql> SET @x = '{ "a": 1, "b": 2 }',
> @y = '{ "a": 3, "c": 4 }',
> @z = '{ "a": 5, "d": 6 }';
mysql> SELECT JSON_MERGE_PATCH(@x, @y, @z) AS Patch,
-> JSON_MERGE_PRESERVE(@x, @y, @z) AS Preserve\G
*************************** 1. row ***************************
Patch: {"a": 5, "b": 2, "c": 4, "d": 6}
Preserve: {"a": [1, 3, 5], "b": 2, "c": 4, "d": 6}
12.18.4.8 JSON_REMOVE(json_doc, path[, path] ...)
从 JSON 文档中删除数据并返回结果。
- 如果任何参数是
NULL
则返回NULL
。 - 如果参数*
json_doc
不是有效的 JSON 文档或任何path
*参数不是有效的路径表达式或者是$
或包含*
or**
通配符, 则会发生错误 。
*path
*参数从左到右进行评估 。通过评估一个路径生成的文档成为评估下一个路径的新值。
如果要删除的元素在文档中不存在,则不是错误;在这种情况下,路径不会影响文档。
mysql> SET @j = '["a", ["b", "c"], "d"]';
mysql> SELECT JSON_REMOVE(@j, '$[1]');
+-------------------------+
| JSON_REMOVE(@j, '$[1]') |
+-------------------------+
| ["a", "d"] |
+-------------------------+
12.18.4.9 JSON_REPLACE(json_doc, path, val[, path, val] ...)
替换 JSON 文档中的现有值并返回结果。
- 如果任何参数是
NULL
则返回NULL
。 - 如果参数*
json_doc
不是有效的 JSON 文档或任何path
*参数不是有效的路径表达式或包含*
或**
通配符, 则会发生错误 。
path-value对从左到右进行评估。通过评估一对生成的文档成为评估下一对的新值。
文档中现有路径的path-value对用新值覆盖现有文档值。文档中不存在路径的path-value对将被忽略且无效。
有关 JSON_INSERT()
、 JSON_REPLACE()
JSON_SET()
的比较, 请参阅 JSON_SET()
的讨论。
mysql> SET @j = '{ "a": 1, "b": [2, 3]}';
mysql> SELECT JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]');
+-----------------------------------------------------+
| JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]') |
+-----------------------------------------------------+
| {"a": 10, "b": [2, 3]} |
+-----------------------------------------------------+
12.18.4.10 JSON_SET(json_doc, path, val[, path, val] ...)
在 JSON 文档中插入或更新数据并返回结果。
- 如果任何参数是
NULL
或*path
*没有找到对象,则返回NULL
。 - 如果参数*
json_doc
不是有效的 JSON 文档或任何path
*参数不是有效的路径表达式或包含*
或**
通配符, 则会发生错误 。
path-value对从左到右进行评估。通过评估一对生成的文档成为评估下一对的新值。
文档中现有路径的path-value对用新值覆盖现有文档值。如果路径标识以下类型的值之一,则文档中不存在路径的path-value对会将值添加到文档中:
- 现有对象中不存在的成员。该成员被添加到对象并与新值相关联。
- 超过现有数组末尾的位置。使用新值扩展数组。如果现有值不是数组,则将其自动包装为数组,然后使用新值进行扩展。
否则,文档中不存在路径的path-value对将被忽略且无效。
JSON_SET()
、 JSON_INSERT()
和 JSON_REPLACE()
函数的关系与区别:
JSON_SET()
替换现有值并添加不存在的值。JSON_INSERT()
插入值而不替换现有值。JSON_REPLACE()
仅替换 现有值。
以下示例说明了这些差异,使用文档中存在的一个路径 ( $.a
) 和不存在的另一个路径 ( $.c
):
mysql> SET @j = '{ "a": 1, "b": [2, 3]}';
mysql> SELECT JSON_SET(@j, '$.a', 10, '$.c', '[true, false]');
+-------------------------------------------------+
| JSON_SET(@j, '$.a', 10, '$.c', '[true, false]') |
+-------------------------------------------------+
| {"a": 10, "b": [2, 3], "c": "[true, false]"} |
+-------------------------------------------------+
mysql> SELECT JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]');
+----------------------------------------------------+
| JSON_INSERT(@j, '$.a', 10, '$.c', '[true, false]') |
+----------------------------------------------------+
| {"a": 1, "b": [2, 3], "c": "[true, false]"} |
+----------------------------------------------------+
mysql> SELECT JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]');
+-----------------------------------------------------+
| JSON_REPLACE(@j, '$.a', 10, '$.c', '[true, false]') |
+-----------------------------------------------------+
| {"a": 10, "b": [2, 3]} |
+-----------------------------------------------------+
12.18.4.11 JSON_UNQUOTE(json_val)
取消引用 JSON 值并将结果作为 utf8mb4
字符串返回。
- 如果参数是
NULL
则返回NULL
。 - 如果值以双引号开头和结尾但不是有效的 JSON 字符串文字,则会发生错误。
在字符串中,某些序列具有特殊含义,除非启用 SQL 模式 NO_BACKSLASH_ESCAPES
。这些序列中的每一个都以反斜杠 ( \
) 开头,称为 转义字符。MySQL 识别 表 12.23,“JSON_UNQUOTE() 特殊字符转义序列”中显示的转义序列。对于所有其他转义序列,反斜杠将被忽略。也就是说,转义字符被解释为好像没有转义。例如,\x
只是x
. 这些序列区分大小写。例如, \b
被解释为退格,但 \B
被解释为B
.
表 12.23 JSON_UNQUOTE() 特殊字符转义序列
转义序列 | 序列表示的字符 |
---|---|
\" | 双引号 ( " ) 字符 |
\b | 退格字符 |
\f | 换页符 |
\n | 换行符(换行符) |
\r | 回车符 |
\t | 制表符 |
\\ | 反斜杠 ( \ ) 字符 |
\uXXXX | Unicode 值的 UTF-8 字节*XXXX * |
此处显示了使用此功能的两个简单示例:
mysql> SET @j = '"abc"';
mysql> SELECT @j, JSON_UNQUOTE(@j);
+-------+------------------+
| @j | JSON_UNQUOTE(@j) |
+-------+------------------+
| "abc" | abc |
+-------+------------------+
mysql> SET @j = '[1, 2, 3]';
mysql> SELECT @j, JSON_UNQUOTE(@j);
+-----------+------------------+
| @j | JSON_UNQUOTE(@j) |
+-----------+------------------+
| [1, 2, 3] | [1, 2, 3] |
+-----------+------------------+
下面的一组示例显示了 禁用和启用 NO_BACKSLASH_ESCAPES
的JSON_UNQUOTE
句柄如何转义 :
mysql> SELECT @@sql_mode;
+------------+
| @@sql_mode |
+------------+
| |
+------------+
mysql> SELECT JSON_UNQUOTE('"\\t\\u0032"');
+------------------------------+
| JSON_UNQUOTE('"\\t\\u0032"') |
+------------------------------+
| 2 |
+------------------------------+
mysql> SET @@sql_mode = 'NO_BACKSLASH_ESCAPES';
mysql> SELECT JSON_UNQUOTE('"\\t\\u0032"');
+------------------------------+
| JSON_UNQUOTE('"\\t\\u0032"') |
+------------------------------+
| \t\u0032 |
+------------------------------+
mysql> SELECT JSON_UNQUOTE('"\t\u0032"');
+----------------------------+
| JSON_UNQUOTE('"\t\u0032"') |
+----------------------------+
| 2 |
+----------------------------+
12.18.5 返回 JSON 值属性的函数
-
JSON_DEPTH(json_doc)
-
JSON_LENGTH(json_doc[, path])
-
JSON_TYPE(json_val)
-
JSON_VALID(val)
12.18.5.1 JSON_DEPTH(json_doc)
返回 JSON 文档的最大深度。
- 如果参数是
NULL
则返回NULL
。 - 如果参数不是有效的 JSON 文档,则会发生错误。
空数组、空对象或标量值的深度为 1。仅包含深度为 1 的元素的非空数组或仅包含深度为 1 的成员值的非空对象的深度为 2。否则,JSON 文档的深度大于 2。
mysql> SELECT JSON_DEPTH('{}'), JSON_DEPTH('[]'), JSON_DEPTH('true');
+------------------+------------------+--------------------+
| JSON_DEPTH('{}') | JSON_DEPTH('[]') | JSON_DEPTH('true') |
+------------------+------------------+--------------------+
| 1 | 1 | 1 |
+------------------+------------------+--------------------+
mysql> SELECT JSON_DEPTH('[10, 20]'), JSON_DEPTH('[[], {}]');
+------------------------+------------------------+
| JSON_DEPTH('[10, 20]') | JSON_DEPTH('[[], {}]') |
+------------------------+------------------------+
| 2 | 2 |
+------------------------+------------------------+
mysql> SELECT JSON_DEPTH('[10, {"a": 20}]');
+-------------------------------+
| JSON_DEPTH('[10, {"a": 20}]') |
+-------------------------------+
| 3 |
+-------------------------------+
12.18.5.2 JSON_LENGTH(json_doc[, path])
返回 JSON 文档的长度,或者,如果给定参数 path
,则返回路径标识的文档中值的长度。
- 如果任何参数是
NULL
或*path
* 参数不标识文档中的值,则返回NULL
。 - 如果参数*
json_doc
*不是有效的 JSON 文档或 *path
*参数不是有效的路径表达式或包含通配符*
或**
通配符, 则会发生错误。
文档的长度确定如下:
- 标量的长度为 1。
- 数组的长度是数组元素的数量。
- 对象的长度是对象成员的数量。
- 长度不计算嵌套数组或对象的长度。
mysql> SELECT JSON_LENGTH('[1, 2, {"a": 3}]');
+---------------------------------+
| JSON_LENGTH('[1, 2, {"a": 3}]') |
+---------------------------------+
| 3 |
+---------------------------------+
mysql> SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}');
+-----------------------------------------+
| JSON_LENGTH('{"a": 1, "b": {"c": 30}}') |
+-----------------------------------------+
| 2 |
+-----------------------------------------+
mysql> SELECT JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b');
+------------------------------------------------+
| JSON_LENGTH('{"a": 1, "b": {"c": 30}}', '$.b') |
+------------------------------------------------+
| 1 |
+------------------------------------------------+
12.18.5.3 JSON_TYPE(json_val)
返回一个utf8mb4
字符串,指示 JSON 值的类型。这可以是对象、数组或标量类型,如下所示:
mysql> SET @j = '{"a": [10, true]}';
mysql> SELECT JSON_TYPE(@j);
+---------------+
| JSON_TYPE(@j) |
+---------------+
| OBJECT |
+---------------+
mysql> SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a'));
+------------------------------------+
| JSON_TYPE(JSON_EXTRACT(@j, '$.a')) |
+------------------------------------+
| ARRAY |
+------------------------------------+
mysql> SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a[0]'));
+---------------------------------------+
| JSON_TYPE(JSON_EXTRACT(@j, '$.a[0]')) |
+---------------------------------------+
| INTEGER |
+---------------------------------------+
mysql> SELECT JSON_TYPE(JSON_EXTRACT(@j, '$.a[1]'));
+---------------------------------------+
| JSON_TYPE(JSON_EXTRACT(@j, '$.a[1]')) |
+---------------------------------------+
| BOOLEAN |
+---------------------------------------+
如果参数为 NULL
则返回 NULL
:
mysql> SELECT JSON_TYPE(NULL);
+-----------------+
| JSON_TYPE(NULL) |
+-----------------+
| NULL |
+-----------------+
如果参数不是有效的 JSON 值,则会发生错误:
mysql> SELECT JSON_TYPE(1);
ERROR 3146 (22032): Invalid data type for JSON data in argument 1
to function json_type; a JSON string or JSON type is required.
对于非NULL
非错误结果,以下列表描述了可能的 JSON_TYPE()
返回值:
- 纯 JSON 类型:
OBJECT
: JSON 对象ARRAY
: JSON 数组BOOLEAN
: JSON真假文字NULL
: JSON 空字面量
- 数字类型:
- 时间类型:
- 字符串类型:
- 二进制类型:
- 所有其他类型:
OPAQUE
(原始位)
12.18.5.4 JSON_VALID(val)
返回 0 或 1 以指示值是否为有效 JSON。如果参数是NULL
则返回NULL
。
mysql> SELECT JSON_VALID('{"a": 1}');
+------------------------+
| JSON_VALID('{"a": 1}') |
+------------------------+
| 1 |
+------------------------+
mysql> SELECT JSON_VALID('hello'), JSON_VALID('"hello"');
+---------------------+-----------------------+
| JSON_VALID('hello') | JSON_VALID('"hello"') |
+---------------------+-----------------------+
| 0 | 1 |
+---------------------+-----------------------+
12.18.6 JSON 实用函数
- JSON_PRETTY(json_val)
- JSON_STORAGE_SIZE(json_val)
本节介绍作用于 JSON 值或可解析为 JSON 值的字符串的实用程序函数。
JSON_PRETTY()
以易于阅读的格式打印出 JSON 值。JSON_STORAGE_SIZE()
显示给定 JSON 值使用的存储空间量。
12.18.6.1 JSON_PRETTY(json_val)
提供类似于 PHP 和其他语言和数据库系统实现的 JSON 值的漂亮打印。提供的值必须是 JSON 值或 JSON 值的有效字符串表示形式。此值中存在的无关空格和换行符对输出没有影响。对于一个NULL
值,该函数返回NULL
。如果该值不是 JSON 文档,或者无法将其解析为一个,则该函数将失败并出现错误。
此函数的输出格式遵循以下规则:
- 每个数组元素或对象成员出现在单独的行上,与父级相比缩进一个额外的级别。
- 每级缩进增加两个前导空格。
- 在分隔两个元素或成员的换行符之前打印分隔单个数组元素或对象成员的逗号。
- 对象成员的键和值由冒号 (’
:
') 和空格分隔。 - 空对象或数组打印在一行上。左大括号和右大括号之间没有打印空格。
- 使用函数
JSON_QUOTE()
使用的相同规则对字符串标量和键名中的特殊字符进行转义 。
mysql> SELECT JSON_PRETTY('123'); # scalar
+--------------------+
| JSON_PRETTY('123') |
+--------------------+
| 123 |
+--------------------+
mysql> SELECT JSON_PRETTY("[1,3,5]"); # array
+------------------------+
| JSON_PRETTY("[1,3,5]") |
+------------------------+
| [
1,
3,
5
] |
+------------------------+
mysql> SELECT JSON_PRETTY('{"a":"10","b":"15","x":"25"}'); # object
+---------------------------------------------+
| JSON_PRETTY('{"a":"10","b":"15","x":"25"}') |
+---------------------------------------------+
| {
"a": "10",
"b": "15",
"x": "25"
} |
+---------------------------------------------+
mysql> SELECT JSON_PRETTY('["a",1,{"key1":
> "value1"},"5", "77" ,
> {"key2":["value3","valueX",
> "valueY"]},"j", "2" ]')\G # nested arrays and objects
*************************** 1. row ***************************
JSON_PRETTY('["a",1,{"key1":
"value1"},"5", "77" ,
{"key2":["value3","valuex",
"valuey"]},"j", "2" ]'): [
"a",
1,
{
"key1": "value1"
},
"5",
"77",
{
"key2": [
"value3",
"valuex",
"valuey"
]
},
"j",
"2"
]
在 MySQL 5.7.22 中添加。
12.18.6.2 JSON_STORAGE_SIZE(json_val)
此函数返回用于存储 JSON 文档的二进制表示的字节数。当参数是JSON
列时,这是用于存储 JSON 文档的空间。json_val
必须是有效的 JSON 文档或可以解析为一个JSON的字符串。在它是字符串的情况下,该函数以 JSON 二进制表示形式返回存储空间量,该表示是通过将字符串解析为 JSON 并将其转换为二进制而创建的。如果参数是NULL
则返回NULL
。
当*json_val
* 不是 NULL
或无法成功解析为 JSON 文档时, 将导致错误。
为了说明此函数在使用 JSON
列作为参数时的行为,我们创建一个名为jtable
的表,其中包含一个 JSON
列jcol
,向表中插入一个 JSON 值,然后使用 JSON_STORAGE_SIZE()
获取该列使用的存储空间,如下所示:
mysql> CREATE TABLE jtable (jcol JSON);
Query OK, 0 rows affected (0.42 sec)
mysql> INSERT INTO jtable VALUES
-> ('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}');
Query OK, 1 row affected (0.04 sec)
mysql> SELECT
-> jcol,
-> JSON_STORAGE_SIZE(jcol) AS Size
-> FROM jtable;
+-----------------------------------------------+------+
| jcol | Size |
+-----------------------------------------------+------+
| {"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"} | 47 |
+-----------------------------------------------+------+
1 row in set (0.00 sec)
根据 JSON_STORAGE_SIZE()
的输出,插入该列的 JSON 文档占用 47 个字节。更新后,该函数显示用于新设置值的存储:
mysql> UPDATE jtable
mysql> SET jcol = '{"a": 4.55, "b": "wxyz", "c": "[true, false]"}';
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT
-> jcol,
-> JSON_STORAGE_SIZE(jcol) AS Size
-> FROM jtable;
+------------------------------------------------+------+
| jcol | Size |
+------------------------------------------------+------+
| {"a": 4.55, "b": "wxyz", "c": "[true, false]"} | 56 |
+------------------------------------------------+------+
1 row in set (0.00 sec)
此函数还显示当前用于在用户变量中存储 JSON 文档的空间:
mysql> SET @j = '[100, "sakila", [1, 3, 5], 425.05]';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;
+------------------------------------+------+
| @j | Size |
+------------------------------------+------+
| [100, "sakila", [1, 3, 5], 425.05] | 45 |
+------------------------------------+------+
1 row in set (0.00 sec)
mysql> SET @j = JSON_SET(@j, '$[1]', "json");
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;
+----------------------------------+------+
| @j | Size |
+----------------------------------+------+
| [100, "json", [1, 3, 5], 425.05] | 43 |
+----------------------------------+------+
1 row in set (0.00 sec)
mysql> SET @j = JSON_SET(@j, '$[2][0]', JSON_ARRAY(10, 20, 30));
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;
+---------------------------------------------+------+
| @j | Size |
+---------------------------------------------+------+
| [100, "json", [[10, 20, 30], 3, 5], 425.05] | 56 |
+---------------------------------------------+------+
1 row in set (0.00 sec)
对于 JSON 文字,此函数也返回当前使用的存储空间,如下所示:
mysql> SELECT
-> JSON_STORAGE_SIZE('[100, "sakila", [1, 3, 5], 425.05]') AS A,
-> JSON_STORAGE_SIZE('{"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"}') AS B,
-> JSON_STORAGE_SIZE('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}') AS C,
-> JSON_STORAGE_SIZE('[100, "json", [[10, 20, 30], 3, 5], 425.05]') AS D;
+----+----+----+----+
| A | B | C | D |
+----+----+----+----+
| 45 | 44 | 47 | 56 |
+----+----+----+----+
1 row in set (0.00 sec)
此功能是在 MySQL 5.7.22 中添加的。