MySQL插入循环存储过程问题:最后一行重复插入如何解决?
这种最后一行重复插入的坑我之前踩过好几次,大概率是 游标循环的逻辑顺序或者结束条件处理错了 ,咱们从最常见的原因开始排查:
1. 游标循环的执行顺序搞反了 #
很多人写游标循环时,会把
INSERT
操作放在
FETCH
之前,这就会导致最后一次循环时,游标已经取不到新数据了,但还是用了上一次的变量值执行插入,造成重复。
错误示例: #
DECLARE done INT DEFAULT FALSE; DECLARE var_col1 INT; DECLARE var_col2 VARCHAR(50); DECLARE cur CURSOR FOR SELECT col1, col2 FROM source_table; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN cur; read_loop: LOOP -- 错误:先插入,再取数据 INSERT INTO target_table (col_a, col_b) VALUES (var_col1, var_col2); FETCH cur INTO var_col1, var_col2; IF done THEN LEAVE read_loop; END IF; END LOOP; CLOSE cur;
正确写法: #
应该先执行
FETCH
,判断是否取到数据,再执行插入:
OPEN cur; read_loop: LOOP FETCH cur INTO var_col1, var_col2; -- 先判断是否没有数据了,直接退出 IF done THEN LEAVE read_loop; END IF; -- 确认有数据再插入 INSERT INTO target_table (col_a, col_b) VALUES (var_col1, var_col2); END LOOP; CLOSE cur;
2. 避免使用游标,改用
INSERT ... SELECT
更稳妥
#
其实在MySQL里,游标循环的效率并不高,而且容易出逻辑错误。如果你的需求是从源表每行生成多行目标数据,完全可以用
INSERT ... SELECT
结合
CROSS JOIN
来实现,彻底避免循环问题。
比如要给源表的每一行生成3条目标数据:
INSERT INTO target_table (col_a, col_b, row_num)
SELECT
s.col1,
s.col2,
nums.num
FROM source_table s
-- 这里用UNION ALL生成需要的行数
CROSS JOIN (