由于建议使用循环意味着需要过程类型的解决方案。这是我的。
任何对从表中获取的任何一条记录进行处理的查询都可以包装在一个过程中,以使其遍历表的每一行,如下所示:
DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;
然后是您示例中的过程(为清楚起见,使用了table_A和table_B)
CREATE PROCEDURE ROWPERROW()
BEGIN
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
SELECT COUNT(*) FROM table_A INTO n;
SET i=0;
WHILE i<n DO
INSERT INTO table_B(ID, VAL) SELECT (ID, VAL) FROM table_A LIMIT i,1;
SET i = i + 1;
END WHILE;
End;
;;
然后不要忘记重置定界符
DELIMITER ;
并运行新程序
CALL ROWPERROW();
您可以在我从示例请求中简单复制的“ INSERT INTO”行中执行任何操作。
请注意,此处使用的“ INSERT INTO”行将反映问题中的行。根据此答案的注释,您需要确保查询在语法上对于所运行的SQL版本均正确。
在您的ID字段递增并从1开始的简单情况下,示例中的行可能变为:
INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;
将“ SELECT COUNT”行替换为
SET n=10;
仅让您在table_A的前10条记录中测试查询。
最后一件事。此过程也非常容易嵌套在不同的表中,这是我可以对一个表执行一个过程的唯一方法,该过程可将父表的每一行中不同数量的记录动态插入到新表中。
如果您需要它运行得更快,请确保尝试将其设置为基础,如果不是,那么就可以了。您也可以用游标形式重写上面的内容,但这可能不会提高性能。例如:
DROP PROCEDURE IF EXISTS cursor_ROWPERROW;
DELIMITER ;;
CREATE PROCEDURE cursor_ROWPERROW()
BEGIN
DECLARE cursor_ID INT;
DECLARE cursor_VAL VARCHAR;
DECLARE done INT DEFAULT FALSE;
DECLARE cursor_i CURSOR FOR SELECT ID,VAL FROM table_A;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor_i;
read_loop: LOOP
FETCH cursor_i INTO cursor_ID, cursor_VAL;
IF done THEN
LEAVE read_loop;
END IF;
INSERT INTO table_B(ID, VAL) VALUES(cursor_ID, cursor_VAL);
END LOOP;
CLOSE cursor_i;
END;
;;
请记住,声明要使用的变量与查询表中的变量相同。
我的建议是,尽可能使用基于集合的查询,并且在必要时仅使用简单的循环或游标。