前言:MySQL JSON 的删除分两个层面:① 删除 JSON 文档内部的 key / 数组元素(JSON_REMOVE);② 删除整条包含 JSON 字段的数据行。很多人容易混淆,本文把两种场景的用法、示例、坑点一次性讲清楚。
一、准备测试表
sql
CREATE TABLE user_info (
id INT PRIMARY KEY AUTO_INCREMENT,
ext JSON COMMENT '用户扩展信息'
);
INSERT INTO user_info(ext)
VALUES ('{"name":"张三","age":22,"phone":"13800138000","tags":["后端","MySQL","开发"],"address":{"city":"重庆","area":"渝北"}}');
二、删除JSON内部的key:JSON_REMOVE
语法:JSON_REMOVE(json_doc, path[, path] ...)
作用:移除 JSON 文档指定路径的数据,返回新的 JSON 文档。支持一次性删除多个key。
1. 删除一级key
删除 phone 字段:
sql
UPDATE user_info
SET ext = JSON_REMOVE(ext, '$.phone')
WHERE id = 1;
2. 删除嵌套对象内的key
删除 address 里面的 area:
sql
UPDATE user_info
SET ext = JSON_REMOVE(ext, '$.address.area')
WHERE id = 1;
3. 一次性删除多个key
同时删除 age 和 address:
sql
UPDATE user_info
SET ext = JSON_REMOVE(ext, '$.age', '$.address')
WHERE id = 1;
三、删除JSON数组中的元素
数组下标从 0 开始,同样使用 JSON_REMOVE。
原始数据:"tags":["后端","MySQL","开发"]
删除下标1的元素(MySQL):
sql
UPDATE user_info
SET ext = JSON_REMOVE(ext, '$.tags[1]')
WHERE id = 1;
⚠️ 重要特性:删除数组元素后,数组下标会自动前移 。
例如:
[A,B,C]删除下标1(B),数组变成[A,C],C 的下标从2变成1。如果循环删除数组元素,必须从后往前删,否则下标错乱。
示例:从后往前删除数组多个元素,避免下标偏移问题
sql
UPDATE user_info
SET ext = JSON_REMOVE(ext, '$.tags[2]','$.tags[1]')
WHERE id = 1;
四、清空JSON字段(置为空对象/空数组)
- 将JSON字段设置为空对象
{}
sql
UPDATE user_info SET ext = JSON_OBJECT() WHERE id = 1;
- 将JSON字段设置为空数组
[]
sql
UPDATE user_info SET ext = JSON_ARRAY() WHERE id = 1;
- 直接置为NULL
sql
UPDATE user_info SET ext = NULL WHERE id = 1;
五、删除整行数据(整条记录)
如果不需要这条记录,直接 DELETE,JSON字段会跟着一起删除:
sql
-- 删除id=1的整行
DELETE FROM user_info WHERE id = 1;
六、根据JSON内部条件删除行
根据JSON内部key的值,筛选并删除整条记录:
sql
-- 删除 ext->name = '张三' 的行
DELETE FROM user_info
WHERE ext->>'$.name' = '张三';
七、高频踩坑点
- JSON_REMOVE 不会修改原数据,必须赋值回字段
sql
-- ❌ 错误写法,不会生效
UPDATE user_info SET JSON_REMOVE(ext, '$.phone') WHERE id=1;
-- ✅ 正确写法,函数返回新json,要赋值给ext
UPDATE user_info SET ext = JSON_REMOVE(ext, '$.phone') WHERE id=1;
- 路径不存在不会报错,直接原样返回
写了错误的path,SQL执行成功,但是数据没有任何变化,不会抛出异常。调试时先用SELECT验证路径:
sql
SELECT JSON_REMOVE(ext, '$.not_exist_key') FROM user_info WHERE id=1;
-
ext字段为NULL时,JSON_REMOVE返回NULL
如果ext本身是NULL,JSON_REMOVE无法操作,不会自动创建JSON对象。
-
生成列索引影响
如果JSON创建了生成列(STORED),删除JSON内对应的key,生成列会同步更新,索引会自动维护,会产生少量性能开销。
-
数组删除下标偏移大坑
数组顺序删除下标0、1、2会出错。因为删掉下标0之后,原来下标1的数据变成下标0。删除多个数组元素,永远从最大下标往最小下标删。
八、选型小结
- 删除JSON内部key/数组元素:
JSON_REMOVE+ UPDATE - 清空JSON字段:
JSON_OBJECT()/JSON_ARRAY()/ NULL - 删除整条记录:
DELETE,支持JSON内部条件过滤 - 数组批量删除:从后往前删除下标,防止下标错位
小提示:如果业务频繁对JSON数组做增删操作,且需要根据数组元素检索,MySQL原生JSON数组性能较差,建议拆成独立子表。