1.游标直接使用入参变量不生效的情况
1.1 作为表名和变量名不生效,不支持拼接
1.2 作为条件的值可以使用
2。解决游标动态获取入参- 通过创建视图view间接实现动态读取入参
实现思路:将变量转变了固定的;
a. 将动态传入的表名,转化为固定的视图里面
b. 通过统一视图*(v_customer_region_view),接收不同表明需要查询的结果字段
1 CREATE PROCEDURE do_modify_reion_data( 2 TableName VARCHAR(68)-- 表名 3 ) 4 BEGIN 5 DECLARE vStr VARCHAR(8000); 6 DECLARE vId int(10); 7 DECLARE done INT; 8 DECLARE indexPage INT; 9 10 -- 定义游标 11 DECLARE custCursor CURSOR 12 FOR 13 SELECT id FROM v_customer_region_view; 14 -- 定义结束标记 15 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; 16 -- 游标查询sql,不支持入参变量直接拼接; 17 -- 通过拼接sql,创建视图,将入参传入的表名,间接固定; 18 -- 并且将sql执行,这个用到了创建视图 v_customer_region_view ,然后将视图作为游标查询的表 19 set @sql =concat("create view v_customer_region_view as select id from ", TableName," where id > 1"); 20 21 -- 这个地方就是将拼接sql执行 22 DROP VIEW IF EXISTS v_customer_region_view; 23 PREPARE stmt1 FROM @sql; 24 EXECUTE stmt1 ; 25 DEALLOCATE PREPARE stmt1; 26 27 SET vStr = ''; 28 SET indexPage = 0; 29 30 -- 打开custCursor游标 31 OPEN custCursor; 32 33 -- 循环vSerialNo 34 custLoop:LOOP 35 36 -- 取游标中的数据 37 FETCH custCursor INTO vId; 38 IF done = 1 THEN 39 LEAVE custLoop; 40 END IF; 41 -- 批量处理100条 42 IF indexPage = 0 THEN 43 SET vStr = CONCAT('(',vStr, vId ); 44 SET indexPage = indexPage +1; 45 ELSE 46 SET vStr = CONCAT(vStr,", ", vId ); 47 SET indexPage = indexPage +1; 48 END IF; 49 50 -- 100条更新一次 51 IF indexPage = 100 THEN 52 SET vStr = CONCAT(vStr,')'); 53 SET @sqlstr = CONCAT( 54 -- sql语句 55 "UPDATE ", TableName, " SET name = 'admin' WHERE id in ",vStr 56 ); 57 -- 日志打印 58 insert into temp_log select concat(' ',@sqlstr); 59 PREPARE stmt FROM @sqlstr; 60 EXECUTE stmt; 61 DEALLOCATE PREPARE stmt; 62 SET indexPage = 0; 63 END IF; 64 65 -- 关闭游标custCursor 66 END LOOP; 67 CLOSE custCursor; 68 IF indexPage >= 1 THEN 69 SET vStr = CONCAT(vStr,')'); 70 71 SET @sqlstr = CONCAT( 72 -- sql语句 73 "UPDATE ", TableName, " SET name = 'admin' WHERE id in ",vStr 74 ); 75 -- 日志打印 76 insert into temp_log select concat('myvar is ',@sqlstr); 77 78 PREPARE stmt FROM @sqlstr; 79 EXECUTE stmt; 80 -- 释放数据资源 81 DEALLOCATE PREPARE stmt; 82 END IF; 83 -- 执行完删除视图 84 DROP VIEW IF EXISTS v_customer_region_view; 85 END; 86 87 -- 日志表 88 89 DROP TABLE IF EXISTS `temp_log`; 90 CREATE TABLE `temp_log` ( 91 `desc` varchar(400) NOT NULL DEFAULT '' COMMENT '存储过程日志' 92 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储过程日志'; 93 游标使用入参表名
两层循环:
-- 过程 DELIMITER && CREATE PROCEDURE proc_updateStatus_JD( TableName VARCHAR(68)-- 表名 ) BEGIN DECLARE vNum INT; DECLARE vcutomerId VARCHAR(40); DECLARE vSerialNo VARCHAR(32); DECLARE vStr VARCHAR(232); DECLARE done INT; DECLARE done_cust INT; -- 定义游标 DECLARE stuCursor CURSOR FOR SELECT customer_id FROM v_customer_id_view; -- 定义cust游标 DECLARE custCursor CURSOR FOR SELECT id FROM v_table_id_view; -- 定义结束标记 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; -- TableName 无法动态传入,通过创建视图(v_customer_id_view)过度 set @sql =concat("create view v_customer_id_view as select customer_id from ", TableName," WHERE channel_code = 'T002000' AND relation_type = '8888' AND tel_sign = 'T01' GROUP BY customer_id HAVING COUNT(1) > 1"); -- insert into temp_log select concat( @sql); -- 这个地方就是将拼接sql执行 DROP VIEW IF EXISTS v_customer_id_view; PREPARE stmt1 FROM @sql; EXECUTE stmt1 ; DEALLOCATE PREPARE stmt1; -- 打开游标 OPEN stuCursor; -- 循环vcutomerId stuLoop:LOOP -- 取游标中的数据 FETCH stuCursor INTO vcutomerId; IF done = 1 THEN LEAVE stuLoop; END IF; set @sql =concat("create view v_table_id_view as select id from ", TableName," where customer_id = '",vcutomerId,"' ORDER BY update_time DESC"); --insert into temp_log select concat( @sql); -- 这个地方就是将拼接sql执行 DROP VIEW IF EXISTS v_table_id_view; PREPARE stmt1 FROM @sql; EXECUTE stmt1 ; DEALLOCATE PREPARE stmt1; SET vNum = 0; -- 打开custCursor游标 OPEN custCursor; -- 循环vSerialNo custLoop:LOOP -- 取游标中的数据 FETCH custCursor INTO vSerialNo; IF done = 1 THEN LEAVE custLoop; END IF; IF vNum > 0 THEN set @sql =concat("update ", TableName," set tel_sign= 'T02' where id = '",vSerialNo,"';"); --insert into temp_log select concat( @sql); -- 这个地方就是将拼接sql执行 DROP VIEW IF EXISTS v_table_id_view; PREPARE stmt1 FROM @sql; EXECUTE stmt1 ; DEALLOCATE PREPARE stmt1; END IF; SET vNum = vNum+1; -- 关闭游标custCursor END LOOP; CLOSE custCursor; SET done =0; END LOOP stuLoop; -- 关闭游标 CLOSE stuCursor; END && DELIMITER ; -- 调用过程 CALL proc_updateStatus_JD('c_tel_info_01'); 双层循环
1 -- 过程 2 DELIMITER && 3 CREATE PROCEDURE proc_updateStatus_JD( 4 TableName VARCHAR(68)-- 表名 5 ) 6 BEGIN 7 DECLARE vNum INT; 8 DECLARE vcutomerId VARCHAR(40); 9 DECLARE vSerialNo VARCHAR(32); 10 DECLARE vStr VARCHAR(232); 11 DECLARE done INT; 12 DECLARE done_cust INT; 13 14 -- 定义游标 15 DECLARE stuCursor CURSOR 16 FOR 17 SELECT customer_id FROM v_customer_id_view; 18 19 -- 定义cust游标 20 DECLARE custCursor CURSOR 21 FOR 22 SELECT id FROM v_table_id_view; 23 24 -- 定义结束标记 25 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; 26 -- TableName 无法动态传入,通过创建视图(v_customer_id_view)过度 27 set @sql =concat("create view v_customer_id_view as select customer_id from ", TableName," WHERE channel_code = 'T002000' AND relation_type = '8888' AND tel_sign = 'T01' GROUP BY customer_id HAVING COUNT(1) > 1"); 28 -- insert into temp_log select concat( @sql); 29 -- 这个地方就是将拼接sql执行 30 DROP VIEW IF EXISTS v_customer_id_view; 31 PREPARE stmt1 FROM @sql; 32 EXECUTE stmt1 ; 33 DEALLOCATE PREPARE stmt1; 34 35 -- 打开游标 36 OPEN stuCursor; 37 38 -- 循环vcutomerId 39 stuLoop:LOOP 40 -- 取游标中的数据 41 FETCH stuCursor INTO vcutomerId; 42 IF done = 1 THEN 43 LEAVE stuLoop; 44 END IF; 45 46 set @sql =concat("create view v_table_id_view as select id from ", TableName," where customer_id = '",vcutomerId,"' ORDER BY update_time DESC"); 47 --insert into temp_log select concat( @sql); 48 49 -- 这个地方就是将拼接sql执行 50 DROP VIEW IF EXISTS v_table_id_view; 51 PREPARE stmt1 FROM @sql; 52 EXECUTE stmt1 ; 53 DEALLOCATE PREPARE stmt1; 54 SET vNum = 0; 55 -- 打开custCursor游标 56 OPEN custCursor; 57 58 -- 循环vSerialNo 59 custLoop:LOOP 60 -- 取游标中的数据 61 FETCH custCursor INTO vSerialNo; 62 IF done = 1 THEN 63 LEAVE custLoop; 64 END IF; 65 66 IF vNum > 0 THEN 67 68 set @sql =concat("update ", TableName," set tel_sign= 'T02' where id = '",vSerialNo,"';"); 69 --insert into temp_log select concat( @sql); 70 71 -- 这个地方就是将拼接sql执行 72 DROP VIEW IF EXISTS v_table_id_view; 73 PREPARE stmt1 FROM @sql; 74 EXECUTE stmt1 ; 75 DEALLOCATE PREPARE stmt1; 76 END IF; 77 SET vNum = vNum+1; 78 -- 关闭游标custCursor 79 END LOOP; 80 CLOSE custCursor; 81 SET done =0; 82 END LOOP stuLoop; 83 -- 关闭游标 84 CLOSE stuCursor; 85 END 86 && 87 DELIMITER ; 88 89 -- 调用过程 90 CALL proc_updateStatus_JD('c_tel_info_01');
CREATE PROCEDURE do_modify_reion_data( TableName VARCHAR(68)-- 表名 ) BEGIN DECLARE vStr VARCHAR(8000); DECLARE vId int(10); DECLARE done INT; DECLARE indexPage INT; -- 定义游标 DECLARE custCursor CURSOR FOR SELECT id FROM v_customer_region_view; -- 定义结束标记 DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; -- 游标查询sql,不支持入参变量直接拼接; -- 通过拼接sql,创建视图,将入参传入的表名,间接固定; -- 并且将sql执行,这个用到了创建视图 v_customer_region_view ,然后将视图作为游标查询的表 set @sql =concat("create view v_customer_region_view as select id from ", TableName," where id > 1"); -- 这个地方就是将拼接sql执行 DROP VIEW IF EXISTS v_customer_region_view; PREPARE stmt1 FROM @sql; EXECUTE stmt1 ; DEALLOCATE PREPARE stmt1; SET vStr = ''; SET indexPage = 0; -- 打开custCursor游标 OPEN custCursor; -- 循环vSerialNo custLoop:LOOP -- 取游标中的数据 FETCH custCursor INTO vId; IF done = 1 THEN LEAVE custLoop; END IF; -- 批量处理100条 IF indexPage = 0 THEN SET vStr = CONCAT('(',vStr, vId ); SET indexPage = indexPage +1; ELSE SET vStr = CONCAT(vStr,", ", vId ); SET indexPage = indexPage +1; END IF; -- 100条更新一次 IF indexPage = 100 THEN SET vStr = CONCAT(vStr,')'); SET @sqlstr = CONCAT( -- sql语句 "UPDATE ", TableName, " SET name = 'admin' WHERE id in ",vStr ); -- 日志打印 insert into temp_log select concat(' ',@sqlstr); PREPARE stmt FROM @sqlstr; EXECUTE stmt; DEALLOCATE PREPARE stmt; SET indexPage = 0; END IF; -- 关闭游标custCursor END LOOP; CLOSE custCursor; IF indexPage >= 1 THEN SET vStr = CONCAT(vStr,')'); SET @sqlstr = CONCAT( -- sql语句 "UPDATE ", TableName, " SET name = 'admin' WHERE id in ",vStr ); -- 日志打印 insert into temp_log select concat('myvar is ',@sqlstr); PREPARE stmt FROM @sqlstr; EXECUTE stmt; -- 释放数据资源 DEALLOCATE PREPARE stmt; END IF; -- 执行完删除视图 DROP VIEW IF EXISTS v_customer_region_view; END; -- 日志表 DROP TABLE IF EXISTS `temp_log`; CREATE TABLE `temp_log` ( `desc` varchar(400) NOT NULL DEFAULT '' COMMENT '存储过程日志' ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='存储过程日志'; 游标使用入参表名