JSON_MERGE_PATCH() 是 MySQL 8.0.3+ 中实现 RFC 7396 覆盖式更新的函数,按键级优先覆盖、浅层替换,适用于配置覆盖、API 补丁等需“以右值为准”的场景,不合并嵌套字段,遇同名键直接替换整值。

JSON_MERGE_PATCH() 是 MySQL 8.0.3+ 中处理 JSON 合并最贴近“覆盖式更新”语义的函数,它不是简单拼接,而是按 RFC 7396 规范做键级优先覆盖 —— 你只要明确想用右侧值覆盖左侧同名键,就该选它,而不是 JSON_MERGE_PRESERVE() 或已弃用的 JSON_MERGE()。
什么时候必须用 JSON_MERGE_PATCH() 而不是 JSON_MERGE_PRESERVE()
当你需要“以最后一个文档为准”的合并逻辑时:JSON_MERGE_PATCH() 会丢弃重复键的所有旧值,只保留最右边参数里的值;而 JSON_MERGE_PRESERVE() 遇到重复键会把所有值收进数组(比如 "a": [1, 4]),这在配置覆盖、API 补丁更新等场景完全不符合预期。
- REST API 的 PATCH 请求体合并:客户端只传了部分字段,你要用它覆盖已有 JSON 字段的对应键
- 用户偏好设置更新:只改
"theme"和"lang",其他字段保持原样,且不希望它们变成数组 - 避免意外生成嵌套数组:用
JSON_MERGE_PRESERVE()多次更新同一键,会导致"retry_count": [3, 5, 7]这种不可用结构
JSON_MERGE_PATCH() 对嵌套对象和数组的处理规则
它不是深度递归合并,而是“浅层替换 + 类型感知”:遇到同名键时,直接用右侧值替换整个左侧值,不管左侧是对象、数组还是标量。
- 两个对象有同名子对象键(如
"profile"):右侧的"profile"完全替换左侧的,不会合并其内部字段 - 左侧是对象,右侧是标量(如
'{"x": 1}'→'"x"):整个"x"键的值被替换成字符串"x",不是报错 - 任一参数为
NULL:整个函数返回NULL,不报错但结果为空 —— 注意判空 - 数组参数:不是逐元素合并,而是整个数组被右侧同名数组替换;若右侧是标量,则数组被替换为该标量(例如
[1,2]→42)
示例:SELECT JSON_MERGE_PATCH('{"user": {"id": 1, "name": "A"}}', '{"user": {"email": "a@b.c"}}');
结果是 {"user": {"email": "a@b.c"}},不是 {"user": {"id": 1, "name": "A", "email": "a@b.c"}}。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
常见错误:误把列值当 JSON 字符串传入
如果你从表里查出一个 JSON 列(比如 config JSON),直接写 JSON_MERGE_PATCH(config, '{"log_level": "debug"}') 是安全的;但若该列实际存的是字符串(VARCHAR)、或内容未通过 JSON_VALID() 校验,函数会静默返回 NULL 或报错 Invalid JSON text。
- 先确认字段类型:
SHOW COLUMNS FROM your_table LIKE 'config';必须显示json - 运行时校验:
WHERE JSON_VALID(config)加在 WHERE 条件里,避免脏数据中断合并 - 不要手动拼接 JSON 字符串:像
CONCAT('{"a":', col_value, '}')极易注入非法字符,改用JSON_OBJECT('a', col_value)
性能与实际使用边界
JSON_MERGE_PATCH() 本身开销很小,但它的行为依赖于 MySQL 的 JSON 二进制解析器 —— 每次调用都会对所有输入做完整语法验证和结构重建。如果在 UPDATE 语句中高频调用(比如每秒数千次),且 JSON 文档较大(>10KB),可能成为瓶颈。
- 小文档(
- 大文档或高并发:考虑在应用层合并后再写入,或拆成多个
JSON_SET()更新特定路径 - 永远不要在 WHERE 子句里对
JSON_MERGE_PATCH()结果做复杂匹配:它无法利用索引,必然触发全表扫描
真正容易被忽略的一点:这个函数不修改原字段,只是计算结果 —— 你得显式用 UPDATE ... SET config = JSON_MERGE_PATCH(config, ?) 才能落地,漏掉赋值就白跑了。

















