MySQL 5.7+ 用 JSON_SET() 更新 JSON 字段,语法为 JSON_SET(COALESCE(col, '{}'), '$.key', value),支持新增或覆盖键值,路径须加单引号且字段为 NULL 时需兜底。

MySQL 5.7+ 怎么用 JSON_SET 更新 JSON 字段里的 key
MySQL 原生支持 JSON,但 UPDATE 不能直接用点号或方括号赋值(比如 SET data.name = 'Alice' 会报错)。必须用 JSON_SET()、JSON_REPLACE() 或 JSON_INSERT() 这类函数。
JSON_SET() 是最常用的选择:它会**新增或覆盖**指定路径的值,路径用 '$.key' 或 '$.list[0].id' 格式写。
常见错误现象:ERROR 3140 (22032): Invalid JSON text —— 多半是路径字符串没加单引号,或者 JSON 字段本身为 NULL 导致函数返回 NULL。
- 路径必须是字符串字面量,例如
'$.status',不能写成$.status - 如果字段可能为
NULL,先用COALESCE(data, '{}')防止整条记录被跳过 - 嵌套路径中数组下标从 0 开始,
'$.items[1].price'才是第二个元素 - 多个属性要改?重复调用
JSON_SET不行,得嵌套写:JSON_SET(JSON_SET(data, '$.a', 1), '$.b', 2)
UPDATE orders
SET data = JSON_SET(COALESCE(data, '{}'), '$.status', 'shipped', '$.updated_at', NOW())
WHERE id = 123;
PostgreSQL 怎么用 jsonb_set 更新 jsonb 字段
PostgreSQL 的 jsonb 类型不支持直接赋值,得靠 jsonb_set()。注意它和 MySQL 的路径语法不同:路径是文本数组,比如 ARRAY['status'],不是 '$.status'。
容易踩的坑:jsonb_set() 第三个参数必须是 jsonb 类型,传字符串会报错;'true' 是文本,'true'::jsonb 才对。
- 路径层级深时,用
ARRAY['user', 'profile', 'age']表示{"user": {"profile": {"age": 30}}} - 想往数组末尾追加?不行,
jsonb_set只能替换或新建,追加得用||拼接或jsonb_insert(PG 14+) - 原字段为
NULL?COALESCE(data, '{}'::jsonb)先兜底 - 想删某个 key?用
data - 'obsolete_field',不是jsonb_set
UPDATE products
SET config = jsonb_set(COALESCE(config, '{}'::jsonb), ARRAY['status'], '"active"'::jsonb, true)
WHERE id = 456;
SQLite 怎么更新 JSON 字段(需要 3.38.0+ 和 json1 扩展)
SQLite 没有原生 JSON 类型,靠 json1 扩展提供函数。更新操作更繁琐:得先用 json_extract() 拿旧值,再拼字符串,最后用 json() 校验格式——本质上是在字符串层面操作。
性能和可读性都较差,所以除非嵌入式场景受限,否则不推荐在 SQLite 里存复杂 JSON 并频繁更新。
-
json_set()函数存在,但只接受单个路径-值对,不能一次改多个 - 路径写法类似 MySQL:
'$.name',但不支持数组索引以外的复杂表达式(如'$.tags[0]'可以,'$.tags[*]'不行) - 务必用
json_valid()检查结果,否则脏数据会静默入库 - 如果字段含单引号,拼接时容易 SQL 注入,优先用参数化查询
UPDATE users
SET metadata = json_set(COALESCE(metadata, '{}'), '$.last_login', datetime('now'))
WHERE id = 789;
UPDATE JSON 字段时最容易被忽略的兼容性细节
不同数据库对空值、路径不存在、类型强制转换的处理差异极大。比如 MySQL 的 JSON_SET(NULL, '$.x', 1) 返回 NULL,而 PostgreSQL 的 jsonb_set(NULL::jsonb, ...) 直接报错;SQLite 则允许对 NULL 调用 json_set 但结果不可靠。
还有:MySQL 8.0.29+ 支持 JSON_TABLE,但 UPDATE 里不能直接用;PostgreSQL 的 jsonb_pretty() 只用于输出,不影响存储;SQLite 的 json_type() 查出来是小写字符串('object'),别跟大写的 JSON 标准描述混淆。
实际写之前,先 SELECT 一条看看原始 JSON 结构,再试函数,比硬写 UPDATE 安全得多。











