Тъй като предложението за цикъл предполага искане за решение от тип процедура. Ето моята.
Всяка заявка, която работи върху всеки отделен запис, взет от таблица, може да бъде обвита в процедура, за да премине през всеки ред на таблицата по следния начин:
Първо изтрийте всяка съществуваща процедура със същото име и променете разделителя, така че вашият SQL да не се опитва да изпълнява всеки ред, докато се опитвате да напишете процедурата.
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;
Ще ви позволи да тествате заявката си само върху първите 10 записа в table_A.
Последно нещо. Този процес също е много лесен за влагане в различни таблици и беше единственият начин, по който можех да извърша процес в една таблица, която динамично вмъква различен брой записи в нова таблица от всеки ред на родителска таблица.
Ако имате нужда от него, за да работи по-бързо, тогава със сигурност опитайте да го настроите базирано, ако не, тогава това е добре. Можете също да пренапишете горното във формата на курсор, но това може да не подобри производителността. напр.:
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;
;;
Не забравяйте да декларирате променливите, които ще използвате, като същия тип като тези от запитаните таблици.
Моят съвет е да използвате заявки, базирани на набори, когато можете, и да използвате обикновени цикли или курсори само ако трябва.