Vì gợi ý của một vòng lặp ngụ ý yêu cầu giải pháp kiểu thủ tục. Đây là của tôi.
Bất kỳ truy vấn nào hoạt động trên bất kỳ bản ghi nào được lấy từ một bảng đều có thể được bao bọc trong một thủ tục để làm cho nó chạy qua từng hàng của bảng như sau:
DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;
Sau đó, đây là quy trình theo ví dụ của bạn (table_A và table_B được sử dụng để rõ ràng)
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;
;;
Sau đó, đừng quên đặt lại dấu phân cách
DELIMITER ;
Và chạy thủ tục mới
CALL ROWPERROW();
Bạn có thể làm bất cứ điều gì bạn thích tại dòng "CHÈN VÀO" mà tôi chỉ cần sao chép từ yêu cầu mẫu của bạn.
Lưu ý CẨN THẬN rằng dòng "CHÈN VÀO" được sử dụng ở đây phản ánh dòng trong câu hỏi. Theo các nhận xét cho câu trả lời này, bạn cần đảm bảo rằng truy vấn của bạn đúng về mặt cú pháp cho phiên bản SQL nào bạn đang chạy.
Trong trường hợp đơn giản khi trường ID của bạn được tăng dần và bắt đầu từ 1 dòng trong ví dụ có thể trở thành:
INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;
Thay thế dòng "SELECT COUNT" bằng
SET n=10;
Sẽ cho phép bạn kiểm tra truy vấn của mình trên 10 bản ghi đầu tiên chỉ trong table_A.
Một điều cuối cùng. Quá trình này cũng rất dễ dàng để lồng trên các bảng khác nhau và là cách duy nhất tôi có thể thực hiện một quy trình trên một bảng để chèn động các số lượng bản ghi khác nhau vào một bảng mới từ mỗi hàng của bảng mẹ.
Nếu bạn cần nó chạy nhanh hơn thì hãy cố gắng đặt nó dựa trên, nếu không thì điều này cũng ổn. Bạn cũng có thể viết lại những điều trên ở dạng con trỏ nhưng nó có thể không cải thiện hiệu suất. ví dụ:
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;
;;
Hãy nhớ khai báo các biến bạn sẽ sử dụng cùng kiểu với các biến từ các bảng được truy vấn.
Lời khuyên của tôi là hãy sử dụng các truy vấn setbased khi bạn có thể và chỉ sử dụng các vòng lặp hoặc con trỏ đơn giản nếu bạn phải.