MySQL 8.x中JSON_VALUE使用变量作为path参数报错问题咨询
报错原因
MySQL 8.0中JSON_VALUE()对第二个path参数存在语法层面的限制:仅接受JSON路径字面量作为入参,不支持传入用户变量、函数拼接生成的动态字符串。你写的JSON_VALUE(@arr, '$[0]')能正常执行,是因为'$[0]'是硬编码的字面量,SQL解析阶段可直接识别为合法路径;传入变量或拼接结果时,解析阶段无法判定参数为合法JSON路径,就会抛出语法错误。
可行解决方案
方案1:使用JSON_EXTRACT替代(推荐)
JSON_EXTRACT()函数的path参数支持传入字符串变量、动态拼接的路径表达式,完全适配循环遍历数组的场景。如果需要提取不带JSON引号的纯标量值,搭配JSON_UNQUOTE()函数即可,效果和JSON_VALUE()取标量值完全一致。
修正后的存储过程代码如下:
CREATE PROCEDURE `tJS` () BEGIN DECLARE _counter INT DEFAULT 0; SET @arr = '["123","3","15"]'; WHILE _counter < JSON_LENGTH(@arr) DO SET @ix = CONCAT('$[', _counter, ']') ; -- 用JSON_EXTRACT提取值,JSON_UNQUOTE去掉JSON格式的包裹引号 SET @v = JSON_UNQUOTE(JSON_EXTRACT(@arr, @ix)); -- 此处编写@v的业务处理逻辑 -- 注意:原代码漏了计数器递增逻辑,会触发死循环,必须补上 SET _counter = _counter + 1; END WHILE; END
该方案无需拼接动态SQL,代码简洁且无额外性能开销,是这类场景的首选实现方式。
方案2:动态SQL兼容JSON_VALUE原生写法
如果你需要用到JSON_VALUE()的独有能力(比如指定返回值类型、自定义空值/报错处理规则),可以通过预处理动态SQL把路径参数拼接为字面量执行,绕开解析阶段的限制。
示例代码如下:
CREATE PROCEDURE `tJS` () BEGIN DECLARE _counter INT DEFAULT 0; SET @arr = '["123","3","15"]'; WHILE _counter < JSON_LENGTH(@arr) DO SET @ix = CONCAT('$[', _counter, ']') ; -- 预处理动态SQL SET @sql = 'SELECT JSON_VALUE(?, ?) INTO @v'; PREPARE stmt FROM @sql; EXECUTE stmt USING @arr, @ix; DEALLOCATE PREPARE stmt; -- 此处@v即为提取到的值,编写后续业务逻辑 SET _counter = _counter + 1; END WHILE; END
该方案存在额外的语句预处理开销,代码冗余度更高,仅在必须使用JSON_VALUE()特定语法时选用。
内容的提问来源于stack exchange,提问作者Dliv
相关产品推荐
相关产品推荐

