Since the loop proposal implies a request for a decision of the type of procedure. Here is mine.
Any query that works with any single record taken from the table can be wrapped in a procedure so that it is executed through each row of the table as follows:
DROP PROCEDURE IF EXISTS ROWPERROW; DELIMITER ;;
Then here is the procedure according to your example (table_A and table_B are used for clarity)
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) VALUES(ID, VAL) FROM table_A LIMIT i,1; SET i = i + 1; END WHILE; End; ;;
Then do not forget to reset the delimiter
DELIMITER ;
And run the new procedure
CALL ROWPERROW();
You can do whatever you want on the line "INSERT INTO", which I just copied from your sample query.
Note. ATTENTION that the line "INSERT INTO" used here reflects the line in the question. In accordance with the comments on this answer, you need to make sure that your query is syntactically correct for which version of SQL you are working for.
In the simple case, when your identifier field increases and starts with 1, the line in the example can become:
INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;
Replacing the string "SELECT COUNT" with
SET n=10;
Allows you to test your query in the first 10 record only in table_A.
Last thing. This process is also very easy to nest in different tables and was the only way I could run a process on one table that dynamically inserted different numbers of records into a new table from each row of the parent table.
If you need it to work faster, then be sure to try installing it based on, if not, then that's fine. You can also rewrite the above in cursor form, but this may not improve performance. eg:
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; ;;
Remember to declare variables that you will use in the same type as those specified in the requested tables.
My advice is to go with the questions asked when possible, and use only simple loops or cursors if you need to.