MySQL用JSON_SET更新嵌套路径更安全,避免字符串拼接导致JSON损坏;PostgreSQL需显式设create_missing=true;SQLite旧版不支持需应用层处理;SQL Server数组要用JSON_QUERY保类型。

MySQL用JSON_SET更新嵌套路径,别硬拼字符串
直接UPDATE SET json_col = '{...}'会覆盖整个字段,丢失原有结构。尤其当JSON里有转义字符(比如extend字段含双引号、反斜杠)时,SQL字符串解析容易出错,导致JSON损坏。
-
JSON_SET(json_col, '$.user.name', 'Alice')只改指定路径,其他字段原样保留 - 路径必须带引号:
'$.data.items[0].id'是对的,$.data.items[0].id会报Syntax error - 布尔值写
true/false,别写"true"——否则存进去是字符串类型 - 数组索引越界(如
$[5]但实际只有3个元素)操作静默失败,不报错也不生效
PostgreSQL用jsonb_set要设create_missing = true
默认jsonb_set(data, '{user,profile,name}', '"Alice"'::jsonb)不会自动创建中间层级。如果user或profile是NULL,结果整个字段变NULL,不是你想要的“补空对象”。
- 第四个参数必须显式传
true:jsonb_set(data, '{user,profile,name}', '"Alice"'::jsonb, true) - 路径是
text[]类型,不是字符串:'{user,profile,name}',不是'$.user.profile.name' - 新值必须是
jsonb类型,字符串得转:'"Alice"'::jsonb或to_jsonb('Alice') - 想同时更新同一子对象多个键(如
profile.first_name和profile.last_name),先用data -> 'profile'取子对象,再用||合并,最后jsonb_set写回
SQLite老版本没json_set,别硬上字符串拼接
SQLite 3.38+ 才支持json_set。Android系统自带的SQLite往往低于此版本,json_set函数根本不存在。
- 用
REPLACE或CONCAT拼JSON字符串极危险:字段含"、\、Unicode时必然崩 - 唯一靠谱做法是应用层读出、解析、修改、序列化、再写回——虽然多一次IO,但安全
- 如果非要SQL层处理,至少先用
json_valid()校验原始值,避免把非法JSON写进去
SQL Server用JSON_MODIFY加JSON_QUERY保类型
直接JSON_MODIFY(json_col, '$.tags', '[1,2,3]')会把数组当成字符串存,后续OPENJSON解析失败。
- 数组类值必须包一层
JSON_QUERY():JSON_MODIFY(json_col, '$.tags', JSON_QUERY('[1,2,3]')) - 拼接新数组时,用
JSON_QUERY()提取原值,再CONCAT拼接,最后仍需JSON_QUERY包裹 - 一次改多个路径(如
$.status和$.updated_at),嵌套调用JSON_MODIFY没问题,但每次都会全量解析JSON,大字段注意性能
JSON_SET自动补,PostgreSQL jsonb_set默认不补,SQL Server JSON_MODIFY也不补。写之前一定确认目标数据库的行为,别靠猜。


















