Já que a sugestão de um loop implica na solicitação de uma solução do tipo procedimento. Aqui é minha.
Qualquer consulta que funcione em qualquer registro único obtido de uma tabela pode ser encapsulada em um procedimento para executá-la em cada linha de uma tabela da seguinte forma:
Primeiro exclua qualquer procedimento existente com o mesmo nome e altere o delimitador para que seu SQL não tente executar cada linha enquanto você está tentando escrever o procedimento.
DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;
Então aqui está o procedimento conforme seu exemplo (table_A e table_B usados para maior clareza)
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;
;;
Então não se esqueça de redefinir o delimitador
DELIMITER ;
E execute o novo procedimento
CALL ROWPERROW();
Você pode fazer o que quiser na linha "INSERT INTO" que eu simplesmente copiei da sua solicitação de exemplo.
Observe CUIDADOSAMENTE que a linha "INSERT INTO" usada aqui espelha a linha na pergunta. De acordo com os comentários desta resposta, você precisa garantir que sua consulta esteja sintaticamente correta para qualquer versão do SQL que você está executando.
No caso simples em que seu campo de ID é incrementado e começa em 1, a linha no exemplo pode se tornar:
INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;
Substituindo a linha "SELECT COUNT" por
SET n=10;
Permitirá que você teste sua consulta apenas nos primeiros 10 registros na tabela_A.
Uma última coisa. Esse processo também é muito fácil de aninhar em diferentes tabelas e foi a única maneira de realizar um processo em uma tabela que inseria dinamicamente diferentes números de registros em uma nova tabela de cada linha de uma tabela pai.
Se você precisar que ele seja executado mais rápido, tente torná-lo definido com base, caso contrário, tudo bem. Você também pode reescrever o acima na forma de cursor, mas pode não melhorar o desempenho. por exemplo:
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;
;;
Lembre-se de declarar as variáveis que você usará como do mesmo tipo daquelas das tabelas consultadas.
Meu conselho é usar consultas baseadas em conjunto quando puder e usar apenas loops ou cursores simples se necessário.