一、目标背景
今天需要修改数据库中的一小部分数据,而逻辑中需要实现一个for循环,将一列数据依次传入目标SQL中作为条件,由于需要改的数据相当小,就不想写代码实现了,于是研究了下怎么用SQL实现;
需求示例(非代码)
ids =(select id from table)
for id in ids{
targetSql: update XXX from table2 where key_id = id;
};
以上非代码,只是防止我对需求场景描述不清造成误解,写的。。。乱码;
二、正式实现
OK,那接下来我们正式开始,我使用的是MySQL数据库,所以这个是适用于MySQL的;
1.创建存储过程
//创建存储过程前先检查是否存在,存在就删除,这个可以忽略
DROP PROCEDURE IF EXISTS staff_zt_test;
//存储过程
CREATE PROCEDURE staff_zt_test()
BEGIN
//该变量用于标识是否还有数据需遍历
DECLARE flag INT DEFAULT 0;
//创建一个变量用来存储遍历过程中的值
DECLARE id BIGINT(40);
//查询出需要遍历的数据集合
DECLARE idList CURSOR FOR (SELECT id FROM table WHERE a = 1);
//查询是否有下一个数据,没有将标识设为1,相当于hasNext
DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
//打开游标
OPEN idList;
//取值设置到临时变量中
FETCH idList INTO id;
//遍历未结束就一直执行
WHILE flag != 1 DO
-- targetSQL //你想要执行的目标功能,这里可以写多个SQL
// 注意
//这里有一个坑,目标语句引用临时变量,实测发现不需要加@符号,但是搜索到的结果都是例如:@id ,这样来使用,实测发现无法取到数据
// 注意
update XXX from table2 where key_id = id;
//一定要记得把游标向后移一位,这个坑我替各位踩过了,不需要再踩了
FETCH idList INTO id;
END WHILE;
CLOSE idList;
END;
2.调用存储过程
//执行存储过程
CALL staff_zt_test();
3.存储过程打印日志
如果没有实现效果,肯定需要调试,这里顺便赠送一个MySQL存储过程日志打印方法;
MySQL是没有PRINT这个关键字的,所以没法直接打印;
使用的是SELECT来实现数据查询,例子如下:
//其他的就不重复注释了,关注注释的地方即可
CREATE PROCEDURE staff_zt_test()
BEGIN
DECLARE flag INT DEFAULT 0;
DECLARE id BIGINT(40);
DECLARE idList CURSOR FOR (SELECT id FROM table WHERE a = 1);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET flag = 1;
OPEN idList;
FETCH idList INTO id;
WHILE flag != 1 DO
//例如打印临时变量 id
SELECT id;
//也可以打印循环外的变量
SELECT flag;
//也可以拼接字符串
SELECT CONCAT('id = ',id,', flag = ',flag);
update XXX from table2 where key_id = id;
FETCH idList INTO id;
END WHILE;
CLOSE idList;
END;
4.本文参考
https://blog.csdn.net/Bulter1996/article/details/91911136
但是这里面就是有上文中提到的坑,引用临时变量上加了@符号,