MySQL存储过程中GROUP_CONCAT聚合函数返回重复值问题
GROUP_CONCAT在存储过程中返回重复值的问题排查与解决
问题现象
在命令行或SQL客户端中使用GROUP_CONCAT聚合函数可正常返回结果,但在存储过程内调用该函数赋值变量时,结果长度符合预期但所有值均重复。
复现场景
测试表结构与数据
假设有表table_name,数据如下:
| test_field | target_field |
|---|---|
| "test_value" | 1 |
| "test_value" | 2 |
| "not_test_value" | 3 |
| "test_value" | 4 |
正常查询示例
直接执行SQL语句可得到正确结果:
SET @array_value := ""; SELECT GROUP_CONCAT(target_field) INTO @array_value FROM `table_name` WHERE `test_field` = 'test_value';
返回结果:"1,2,4"
异常场景代码
该存储过程由table_name的AFTER INSERT触发器触发:
CREATE TRIGGER `cacheAggregate` AFTER INSERT ON `table_name` FOR EACH ROW BEGIN CALL storedProcedureName ( NEW.target_field ); END
存储过程代码:
CREATE PROCEDURE `storedProcedureName`( IN `target_field` VARCHAR ) BEGIN SET @answer_array := ''; SELECT GROUP_CONCAT(target_field) INTO @answer_array FROM `table_name` WHERE `test_field` = "test_value"; INSERT INTO CACHE_TABLE (`answers_array`, `fk_target_field`) VALUES(@answer_array, target_field); END
当插入数据INSERT INTO table_name (test_field,target_field) VALUES ("test_value", 5);时,预期结果为"1,2,4,5",实际返回"5,5,5,5"。
问题根因
命名冲突:存储过程的参数名target_field与表table_name的字段名target_field完全重名,导致SELECT语句中引用的target_field被MySQL解析为存储过程的输入参数,而非表的字段。最终聚合函数反复使用触发器传入的最新插入值,生成全重复的结果。
解决方案
有两种可行的修复方式:
方式1:修改存储过程参数名
将参数名改为与表字段不重复的名称,比如添加前缀p_:
CREATE PROCEDURE `storedProcedureName`( IN `p_target_field` VARCHAR ) BEGIN SET @answer_array := ''; SELECT GROUP_CONCAT(target_field) INTO @answer_array FROM `table_name` WHERE `test_field` = "test_value"; INSERT INTO CACHE_TABLE (`answers_array`, `fk_target_field`) VALUES(@answer_array, p_target_field); END
方式2:明确指定字段所属表/别名
在SELECT语句中通过表名或别名限定字段,避免歧义:
CREATE PROCEDURE `storedProcedureName`( IN `target_field` VARCHAR ) BEGIN SET @answer_array := ''; SELECT GROUP_CONCAT(t.target_field) INTO @answer_array FROM `table_name` t WHERE t.test_field = "test_value"; INSERT INTO CACHE_TABLE (`answers_array`, `fk_target_field`) VALUES(@answer_array, target_field); END
内容的提问来源于stack exchange,提问作者Joshua Albert
相关产品推荐
相关产品推荐

