Poiché il suggerimento di un ciclo implica la richiesta di una soluzione di tipo procedura. Ecco il mio.
Qualsiasi query che funziona su un singolo record preso da una tabella può essere racchiusa in una procedura per farla scorrere su ogni riga di una tabella in questo modo:
DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;
Quindi ecco la procedura come nel tuo esempio (table_A e table_B usati per chiarezza)
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;
;;
Quindi non dimenticare di reimpostare il delimitatore
DELIMITER ;
Ed esegui la nuova procedura
CALL ROWPERROW();
Puoi fare quello che vuoi nella riga "INSERT INTO" che ho semplicemente copiato dalla tua richiesta di esempio.
Notare ATTENTAMENTE che la riga "INSERT INTO" utilizzata qui rispecchia la riga nella domanda. In base ai commenti a questa risposta, è necessario assicurarsi che la query sia sintatticamente corretta per quale versione di SQL si sta eseguendo.
Nel semplice caso in cui il tuo campo ID è incrementato e inizia da 1 la riga nell'esempio potrebbe diventare:
INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;
Sostituendo la riga "SELECT COUNT" con
SET n=10;
Ti consentirà di testare la tua query solo sui primi 10 record nella tabella_A.
Un'ultima cosa. Questo processo è anche molto facile da annidare su tabelle diverse ed era l'unico modo in cui ho potuto eseguire un processo su una tabella che inseriva dinamicamente diversi numeri di record in una nuova tabella da ogni riga di una tabella padre.
Se hai bisogno che funzioni più velocemente, prova a impostarlo in base, altrimenti va bene. È anche possibile riscrivere quanto sopra sotto forma di cursore, ma potrebbe non migliorare le prestazioni. per esempio:
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;
;;
Ricorda di dichiarare le variabili che utilizzerai dello stesso tipo di quelle delle tabelle interrogate.
Il mio consiglio è di andare con le query basate su set quando è possibile e utilizzare solo cicli o cursori semplici se necessario.