json_remove() 是唯一能原地删除 json 字段指定路径元素的函数,无需取出解析再写回;它通过字符串字面量路径操作,静默失败于路径错误,按参数顺序依次处理且后续路径基于前次修改结果计算。

JSON_REMOVE() 是唯一能原地删除 JSON 字段中指定路径元素的函数,不需要取出、解析、拼接再写回——这是它和 UPDATE ... SET col = REPLACE(col, ...) 的本质区别。
用 JSON_REMOVE() 删除单个键或数组元素
最常见场景:清理用户表中已废弃的 "old_config" 字段或日志 JSON 中过期的数组项。
- 语法必须是
JSON_REMOVE(json_doc, path1, path2, ...),path必须用字符串字面量(带引号),不能是变量或列名直接拼接 - 路径写错不会报错,而是静默失败——比如误写
'$.old_config'但实际字段叫'$.legacy_config',语句执行成功但没删掉任何东西 - 数组索引从 0 开始,
'$[0]'删第一个元素;若索引越界(如'$[99]'),该路径被忽略,其余路径仍生效 - 示例:删除
info字段里的temp_flag和数组第 2 项:UPDATE t_json SET info = JSON_REMOVE(info, '$.temp_flag', '$[2]') WHERE id = 1;
批量删除多个路径时注意顺序和嵌套影响
MySQL 按参数从左到右依次处理路径,且**后续路径基于前一次修改后的文档计算**——这点极易踩坑。
- 例如原始 JSON 是
{"a": {"b": 1, "c": 2}, "d": 3},执行JSON_REMOVE(doc, '$.a.b', '$.a'):先删b,此时a变成{"c": 2},再删a才真正移除整个对象 - 但如果反过来写成
JSON_REMOVE(doc, '$.a', '$.a.b'):第一步就删掉了a,第二步的'$.a.b'已不存在,被忽略 - 要安全删整个子对象及其内部所有键,只写顶层路径即可,不用额外列内部路径
- 对数组使用
'$[*]'(MySQL 8.0.17+)可一次性清空所有元素,但不会删掉该数组字段本身
WHERE 条件里用 JSON_CONTAINS_PATH() 避免无效更新
直接对全表执行 JSON_REMOVE() 可能大量命中不含目标路径的记录,徒增 I/O 和 binlog 体积。
- 先用
JSON_CONTAINS_PATH(info, 'one', '$.obsolete_field')筛出确实含该字段的行,再更新:UPDATE t_json SET info = JSON_REMOVE(info, '$.obsolete_field') WHERE JSON_CONTAINS_PATH(info, 'one', '$.obsolete_field');
-
'one'表示“至少存在一个匹配路径”,'all'要求全部路径都存在(用于多路径判断) - 注意:如果字段值为
NULL或非 JSON 类型,JSON_CONTAINS_PATH()返回NULL,在WHERE中等价于FALSE,天然跳过 - 性能上,这个条件无法走索引,但比无条件全表更新更可控
真正容易被忽略的是路径有效性验证——JSON_REMOVE() 不校验路径是否真实存在,也不告诉你删没删成。上线前务必用 SELECT 加 JSON_EXTRACT() 对照验证,尤其是涉及动态拼接路径的业务逻辑。











