json_set强制新增或覆盖字段,json_replace仅更新已有字段;局部更新需满足列类型为json、单函数调用、路径不越界且新值字节不超原值。

MySQL 的 JSON 字段支持局部更新,但必须满足硬性条件,否则看似执行成功,实则整列重写甚至值未变。
JSON_SET 和 JSON_REPLACE 的行为差异必须分清
这两个函数名字像、参数像,但语义完全不同:
-
JSON_SET():不管路径是否存在,都强制设置(新增或覆盖)。例如JSON_SET(info, '$.status', 'done'),即使原 JSON 没有status字段,也会插入; -
JSON_REPLACE():只替换**已存在**的路径。若'$.status'根本不存在,该操作静默失败——不报错、不生效、ROW_COUNT()返回 0; - 误用
JSON_REPLACE()去“新增字段”,会导致 update 看似成功,查数据却发现没变; - 想确保字段一定存在(比如初始化新字段),只能用
JSON_SET();想安全地“仅改已有字段,防误增”,才用JSON_REPLACE()。
局部更新不生效的常见原因
哪怕用了 JSON_SET(),MySQL 也未必走局部更新(in-place)路径,而是整列解析+序列化重写。必须同时满足:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
- 目标列类型是
JSON(不是VARCHAR或TEXT); -
UPDATE语句中只调用JSON_SET()、JSON_REPLACE()或JSON_REMOVE()之一,且不能嵌套其他表达式(如CONCAT(JSON_SET(...), ...)就会失效); - 所有路径都指向**已有对象/数组内的已有位置**:不能在顶层对象里新增 key(如
'$.new_field'),也不能往数组末尾追加(如'$[99]'超出当前长度); - 新值的 UTF-8 编码字节数 ≤ 原值字节数,否则仍会整列重写(比如把短字符串 "on" 改成长字符串 "activated" 就可能触发)。
多路径批量更新要小心参数顺序
JSON_SET() 和 JSON_REPLACE() 都支持一次传多组 path, value,但顺序很重要:
- 参数必须成对出现:
JSON_SET(json_col, '$.a', 1, '$.b', 2)合法;JSON_SET(json_col, '$.a', 1, 2)会报错; - 如果多个 path 指向同一层级,后写的会覆盖先写的(按参数顺序从左到右执行);
- 不要混用
JSON_SET()和JSON_REPLACE()在同一个语句里——语法不允许,MySQL 直接拒绝; - 更新数组元素时,路径写法是
'$[0]'、'$[1]',不是'$.0'(后者会被当作文本 key 处理)。
真正决定是否局部更新的,不是你写了什么函数,而是 MySQL 内部能否在原 JSON 二进制结构上做原地 patch。路径越深、越靠近叶子、越不越界,越容易成功;一旦涉及新增顶层 key 或编码膨胀,就退回保守模式。别只看 ROW_COUNT(),得用 EXPLAIN FORMAT=JSON 查执行计划,或监控 Innodb_buffer_pool_reads 突增来反推是否发生了整列重写。










