Protože návrh smyčky implikuje požadavek na řešení typu procedury. Tady je můj.
Jakýkoli dotaz, který funguje na libovolném jednotlivém záznamu převzatém z tabulky, lze zabalit do procedury, aby proběhl každým řádkem tabulky takto:
Nejprve odstraňte jakoukoli existující proceduru se stejným názvem a změňte oddělovač, aby se váš SQL nepokoušel spustit každý řádek, když se pokoušíte napsat proceduru.
DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;
Pak je zde postup podle vašeho příkladu (tabulka_A a tabulka_B použité pro přehlednost)
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;
;;
Pak nezapomeňte resetovat oddělovač
DELIMITER ;
A spusťte nový postup
CALL ROWPERROW();
Na řádku „INSERT INTO“, který jsem jednoduše zkopíroval z vašeho vzorového požadavku, můžete dělat, co chcete.
POZORNĚ si všimněte, že zde použitý řádek "INSERT INTO" zrcadlí řádek v otázce. Podle komentářů k této odpovědi se musíte ujistit, že váš dotaz je syntakticky správný pro kteroukoli verzi SQL, kterou používáte.
V jednoduchém případě, kdy je vaše pole ID zvýšeno a začíná na 1, řádek v příkladu může vypadat takto:
INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;
Nahrazení řádku "SELECT COUNT" znakem
SET n=10;
Umožní vám otestovat váš dotaz pouze na prvních 10 záznamu v tabulce_A.
Poslední věc. Tento proces je také velmi snadné vnořit do různých tabulek a byl to jediný způsob, jak jsem mohl provést proces na jedné tabulce, který dynamicky vkládal různé počty záznamů do nové tabulky z každého řádku nadřazené tabulky.
Pokud potřebujete, aby běžel rychleji, zkuste jej nastavit na základě, pokud ne, pak je to v pořádku. Můžete také přepsat výše uvedené ve formě kurzoru, ale nemusí to zlepšit výkon. např.:
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;
;;
Nezapomeňte deklarovat proměnné, které budete používat, jako stejný typ jako proměnné z dotazovaných tabulek.
Moje rada je používat dotazy založené na množinách, když můžete, a používat pouze jednoduché smyčky nebo kurzory, pokud musíte.