JSON_EXTRACT返回NULL主因是路径错误或值缺失,且需用->>或JSON_UNQUOTE提取裸值;判断key存在应使用JSON_CONTAINS_PATH而非IS NOT NULL。

存储过程里JSON_EXTRACT为什么总返回NULL?
因为MySQL 8.0存储过程默认启用STRICT_TRANS_TABLES,而JSON_EXTRACT对路径错误、key缺失或非JSON值一律静默返回NULL——这个NULL若直接赋给DECLARE的非NULL变量,或参与IF v_age > 18这类比较,结果恒为FALSE,逻辑就“卡住”了。
- 路径写成
'$.user.name'但实际是'$.profile.name'→ 返回NULL,无报错 -
SET v_name = JSON_EXTRACT(in_json, '$.name');→v_name存的是"张三"(带双引号),不是字符串张三 -
SELECT JSON_EXTRACT('{"a":1}', '$.b')在查询中可见,但在存储过程中被赋值后就“消失”了,很难察觉
提取JSON值必须用->>或JSON_UNQUOTE
90%的业务场景要的是裸值,不是JSON类型包装过的字符串或数字。硬编码JSON_UNQUOTE是安全底线,->>是等价且更简洁的写法。
- 正确:
SET v_name = in_json->>'$.name';或SET v_name = JSON_UNQUOTE(JSON_EXTRACT(in_json, '$.name')); - 错误:
SET v_name = JSON_EXTRACT(in_json, '$.name');→ 后续v_name = '张三'永远FALSE - 数字同理:
in_json->>'$.age'得到可直接参与INT运算的纯数字;漏掉->>,它还是JSON类型的25,在WHERE或ORDER BY中可能被当字符串处理 -
JSON_UNQUOTE(NULL)仍返回NULL,不会报错,可放心用于所有提取路径
判断key是否存在不能只靠IS NOT NULL
JSON_EXTRACT(in_json, '$.email') IS NOT NULL无法区分“key不存在”、“key存在但值为null”、“整个字段为NULL”这三种情况——全返回NULL。
- 检查key是否存在(不管值):
IF JSON_CONTAINS_PATH(in_json, 'one', '$.email') THEN - 检查key存在且非
null:IF JSON_CONTAINS_PATH(in_json, 'one', '$.email') AND JSON_EXTRACT(in_json, '$.email') IS NOT NULL THEN - 别写成
IF in_json->'$.email' IS NOT NULL→->不脱壳,返回仍是JSON类型,IS NOT NULL判断无效
更新JSON字段优先用JSON_REPLACE,慎用JSON_SET
JSON_SET在存储过程中有三个隐性风险:字段本身为NULL时结果仍是NULL;路径不存在时强行新增键,破坏结构;并发写入无锁保护,可能覆盖他人修改。
- 安全更新(仅修改已有key):
SET new_json = JSON_REPLACE(in_json, '$.timeout', v_timeout); - 新增或覆盖都允许(但需确认结构容错):
SET new_json = JSON_SET(in_json, '$.timeout', v_timeout); - 若
in_json可能为NULL,先做判空:IF in_json IS NULL THEN SET new_json = JSON_OBJECT('timeout', v_timeout); ELSE ...
真正麻烦的不是语法,而是你写完JSON_EXTRACT没加->>,又用IS NOT NULL去判断key存在性——这两处漏掉,逻辑就静默失效,查日志都找不到痕迹。


















