文档首页
MySQL 8.4 参考手册
相关文档 下载本手册
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
手册页 (TGZ) - 258.5Kb
手册页 (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 参考手册  /  ...  /  修改 JSON 值的函数

14.17.4 修改 JSON 值的函数

本节中的函数修改 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 文档中识别任何数组的配对,将被忽略。如果路径识别数组元素,则将相应的 value 插入到该元素位置,并将任何后续 value 向右移动。如果路径识别数组末尾后的数组位置,则将 value 插入到数组末尾。

    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 参数不是有效的路径表达式,或者包含 *** 通配符,则会发生错误。

    路径-值对从左到右进行评估。通过评估一对产生的文档将成为评估下一对的新值。

    文档中现有路径的路径-值对将被忽略,不会覆盖现有文档值。文档中不存在的路径的路径-值对将 value 添加到文档中,如果路径识别以下类型的 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)
  • JSON_MERGE(json_doc, json_doc[, json_doc] ...)

    JSON_MERGE_PRESERVE() 的已弃用同义词。

  • JSON_MERGE_PATCH(json_doc, json_doc[, json_doc] ...)

    对两个或多个 JSON 文档执行符合 RFC 7396 的合并,并返回合并后的结果,不保留具有重复键的成员。如果传递给此函数的参数中至少有一个文档无效,则会引发错误。

    注意

    有关此函数与 JSON_MERGE_PRESERVE() 之间差异的解释和示例,请参阅 JSON_MERGE_PATCH() 与 JSON_MERGE_PRESERVE() 的比较

    JSON_MERGE_PATCH() 按如下方式执行合并

    1. 如果第一个参数不是对象,则合并的结果与将空对象与第二个参数合并相同。

    2. 如果第二个参数不是对象,则合并的结果是第二个参数。

    3. 如果两个参数都是对象,则合并的结果是一个对象,其中包含以下成员

      • 第一个对象的所有成员,这些成员在第二个对象中没有与之对应的具有相同键的成员。

      • 第二个对象的所有成员,这些成员在第一个对象中没有与之对应的键,并且其值不是 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() 删除第一个对象中任何与第二个对象中的键匹配的成员,前提是第二个对象中与该键关联的值不是 JSON null

    • 如果第二个对象具有与第一个对象中的成员的键匹配的成员,则 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_docpathNULL,或者如果给定时 path 无法定位对象,则返回 NULL。否则,如果 json_doc 参数不是有效的 JSON 文档,或者任何 path 参数不是有效的路径表达式,或者包含 *** 通配符,则会发生错误。

    路径-值对从左到右进行评估。通过评估一对产生的文档将成为评估下一对的新值。

    文档中现有路径的路径-值对将用新值覆盖现有文档值。文档中不存在的路径的路径-值对将根据路径标识的以下类型的值之一将值添加到文档中

    • 现有对象中不存在的成员。该成员将被添加到对象并与新值关联。

    • 现有数组末尾后的位置。该数组将使用新值进行扩展。如果现有值不是数组,则将其自动包装为数组,然后使用新值进行扩展。

    否则,文档中不存在的路径的路径-值对将被忽略,不会产生任何影响。

    优化器可以对 JSON 列进行部分就地更新,而不是删除旧文档并将其完整写入列。对于使用 JSON_SET() 函数并满足 JSON 值的部分更新 中概述的条件的更新语句,可以执行此优化。

    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_UNQUOTE(json_val)

    取消 JSON 值的引用并将其作为 utf8mb4 字符串返回。如果参数为 NULL,则返回 NULL。如果值以双引号开头和结尾,但不是有效的 JSON 字符串文字,则会发生错误。

    在字符串内,某些序列具有特殊含义,除非启用了 NO_BACKSLASH_ESCAPES SQL 模式。这些序列中的每一个都以反斜杠 (\) 开头,称为 转义字符。MySQL 识别 表 14.23, “JSON_UNQUOTE() 特殊字符转义序列” 中显示的转义序列。对于所有其他转义序列,反斜杠将被忽略。也就是说,转义的字符被解释为没有转义。例如,\x 就是 x。这些序列区分大小写。例如,\b 被解释为退格符,但 \B 被解释为 B

    表 14.23 JSON_UNQUOTE() 特殊字符转义序列

    转义序列 序列表示的字符
    \" 双引号 (") 字符
    \b 退格符
    \f 换页符
    \n 换行符(换行符)
    \r 回车符
    \t 制表符
    \\ 反斜杠 (\) 字符
    \uXXXX Unicode 值 XXXX 的 UTF-8 字节

    此处显示了两个简单的使用此函数的示例

    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                         |
    +----------------------------+