本节中的函数修改 JSON 值并返回结果。
-
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"] | +---------------------------------+
-
JSON_ARRAY_INSERT(
json_doc
,path
,val
[,path
,val
] ...)更新 JSON 文档,将值插入文档中的数组中,并返回修改后的文档。如果任何参数为
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()
调用中的后续路径应该考虑到这一点。在最后一个示例中,第二个路径不插入任何内容,因为路径不再匹配任何内容 после第一次插入。 -
JSON_INSERT(
json_doc
,path
,val
[,path
,val
] ...)将数据插入 JSON 文档中,并返回结果。如果任何参数为
NULL
,则返回NULL
。如果json_doc
参数不是有效的 JSON 文档,或者任何path
参数不是有效的路径表达式或包含*
或**
通配符,则发生错误。路径值对从左到右进行评估。一个对的评估结果将成为下一个对的评估值。
如果路径已经存在于文档中,那么该路径值对将被忽略,不会覆盖文档中的现有值。如果路径不存在于文档中,那么该路径值对将添加到文档中,如果路径识别以下类型的值:
-
对象中的不存在的成员。成员将被添加到对象中,并与新值关联。
-
数组的末尾位置。数组将被扩展到新值。如果现有的值不是数组,那么它将被自动包装为数组,然后扩展到新值。
否则,对于文档中不存在的路径的路径值对将被忽略,不会产生任何效果。
有关
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)
-
-
JSON_MERGE(
json_doc
,json_doc
[,json_doc
] ...)已弃用的同义词
JSON_MERGE_PRESERVE()
。 -
JSON_MERGE_PATCH(
json_doc
,json_doc
[,json_doc
] ...)执行两个或多个 JSON 文档的 RFC 7396 兼容合并,并返回合并后的结果,不保留具有重复键的成员。如果至少一个文档作为函数的参数传递时无效,将引发错误。
Note有关此函数与
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() 与 JSON_MERGE_PRESERVE() 的比较
JSON_MERGE_PATCH()
的行为与JSON_MERGE_PRESERVE()
相同,除了以下两个例外:-
JSON_MERGE_PATCH()
删除第一个对象中具有匹配键的任何成员,前提是第二个对象中的键对应的值不是 JSONnull
。 -
如果第二个对象具有与第一个对象中的成员匹配的键,
JSON_MERGE_PATCH()
替换 第一个对象中的值,而JSON_MERGE_PRESERVE()
追加 第二个值到第一个值。
这个示例比较了使用这两个函数合并相同的 3 个 JSON 对象,每个对象具有匹配的键
"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}
-
-
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} | +----------------------------------------------------------------------------------+
该函数类似于但在重要方面不同于
JSON_MERGE_PATCH()
;请参阅JSON_MERGE_PATCH() 与 JSON_MERGE_PRESERVE() 的比较,以获取更多信息。 -
-
JSON_REMOVE(
json_doc
,path
[,path
] ...)从 JSON 文档中删除数据并返回结果。如果任何参数为
NULL
,则返回NULL
。如果json_doc
参数不是有效的 JSON 文档,或者任何path
参数不是有效的路径表达式或包含*
或**
通配符,则发生错误。评估
path
参数从左到右。评估一个路径后,产生的文档将成为下一个路径的新值。如果要删除的元素不存在于文档中,不会发生错误;在这种情况下,路径不影响文档。
mysql> SET @j = '["a", ["b", "c"], "d"]'; mysql> SELECT JSON_REMOVE(@j, '$[1]'); +-------------------------+ | JSON_REMOVE(@j, '$[1]') | +-------------------------+ | ["a", "d"] | +-------------------------+
-
JSON_REPLACE(
json_doc
,path
,val
[,path
,val
] ...)在 JSON 文档中替换现有值并返回结果。如果任何参数为
NULL
,则返回NULL
。如果json_doc
参数不是有效的 JSON 文档,或者任何path
参数不是有效的路径表达式或包含*
或**
通配符,则发生错误。评估路径值对从左到右。评估一个对后,产生的文档将成为下一个对的新值。
如果文档中已经存在路径,则路径值对将覆盖现有文档值。如果文档中不存在路径,则忽略路径值对且不产生任何效果。
优化器可以对
JSON
列进行部分、就地更新,而不是删除旧文档并将新文档写入列中。该优化可以在使用JSON_REPLACE()
函数并满足 JSON 值的部分更新 中所述条件的更新语句中进行。有关
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]} | +-----------------------------------------------------+
-
JSON_SET(
json_doc
,path
,val
[,path
,val
] ...)在 JSON 文档中插入或更新数据并返回结果。如果
json_doc
或path
为NULL
,或者如果path
不位于对象中,则返回NULL
。否则,如果json_doc
参数不是有效的 JSON 文档,或者任何path
参数不是有效的路径表达式或包含*
或**
通配符,则发生错误。评估路径值对从左到右。评估一个对后,产生的文档将成为下一个对的新值。
如果文档中已经存在路径,则路径值对将覆盖现有文档值。如果文档中不存在路径,则添加值到文档中,如果路径标识以下类型的值:
-
对象中不存在的成员。成员将被添加到对象中,并与新值关联。
-
数组的末尾位置。数组将被扩展到新值。如果现有值不是数组,将被自动包装为数组,然后扩展到新值。
否则,如果文档中不存在路径,则忽略路径值对且不产生任何效果。
优化器可以对
JSON
列执行部分、就地更新,而不是删除旧文档并将新文档写入列中。该优化可以对使用JSON_SET()
函数并满足 JSON 值的部分更新 中所述条件的更新语句进行。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]} | +-----------------------------------------------------+
-
-
取消引号 JSON 值并将结果作为
utf8mb4
字符串返回。如果参数为NULL
,则返回NULL
。如果值以双引号开始和结束,但不是有效的 JSON 字符串文字,则发生错误。在字符串中,一些序列具有特殊含义,除非启用
NO_BACKSLASH_ESCAPES
SQL 模式。在每个序列中,反斜杠 (\
) 是 转义字符。MySQL 识别 表 14.23,“JSON_UNQUOTE() 特殊字符转义序列” 中所示的转义序列。对于所有其他转义序列,反斜杠被忽略。也就是说,被转义的字符被解释为未被转义的字符。例如,\x
只是x
。这些序列区分大小写。例如,\b
被解释为退格,但\B
被解释为B
。
以下两个简单的示例展示了该函数的使用:
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] | +-----------+------------------+
以下一组示例展示了
JSON_UNQUOTE
如何处理带NO_BACKSLASH_ESCAPES
禁用和启用的转义: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 | +----------------------------+