How can I loop through all rows of a table? (MySQL)

I have a table A and there is one primary key ID.

Now I want to go through all rows in A.

I found something like 'for each record in A', but this seems to be not how you do it in MySQL.

Thing is for each row I want to take a field and transform it, insert it into another table and then update some of the row's fields. I can put the select part and the insert into one statement, but I don't know how to get the update in there as well. So I want to loop. And for practice I don't want to use anything else than MySQL.

edit

I would appreciate an example.

And a solution which does not need to be put into a procedure.

edit 2

okay think of this scenario:

Table A and B, each with fields ID and VAL.

Now this is the pseudo code for what I want to do:

for(each row in A as rowA)
{
insert into B(ID, VAL) values(rowA[ID], rowA[VAL]);
}

basically copying content of A into B using a loop.

(this is just a simplified example, of course you wouldn't use a loop for this.) }

349122 次浏览

CURSORS 是这里的一个选项,但是通常不被认可,因为它们通常不能最好地利用查询引擎。考虑调查“基于 SET 的查询”,看看是否可以不使用 CURSOR 实现您想要的操作。

实际上,您应该使用基于集合的解决方案,其中包括两个查询(基本插入) :

INSERT INTO TableB (Id2Column, Column33, Column44)
SELECT id, column1, column2 FROM TableA


UPDATE TableA SET column1 = column2 * column3

至于你的变身:

INSERT INTO TableB (Id2Column, Column33, Column44)
SELECT
id,
column1 * column4 * 100,
(column2 / column12)
FROM TableA


UPDATE TableA SET column1 = column2 * column3

现在,如果您的转换比这更复杂,并且涉及到多个表,请提出另一个带有详细信息的问题。

因为循环的建议意味着对过程类型解决方案的请求。

对从表中获取的任何单个记录运行的任何查询都可以包装在一个过程中,以使其在表的每一行中运行,如下所示:

首先删除任何具有相同名称的现有过程,并更改分隔符,以便在您尝试编写过程时 SQL 不会尝试运行每一行。

DROP PROCEDURE IF EXISTS ROWPERROW;
DELIMITER ;;

然后按照您的示例执行下面的过程(为了清楚起见,使用了 table _ A 和 table _ B)

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;
;;

然后不要忘记重置分隔符

DELIMITER ;

And run the new procedure

CALL ROWPERROW();

您可以在“ INSERTINTO”行中执行任何您喜欢的操作,我只是从您的示例请求中复制了该行。

请注意,这里使用的“ INSERT INTO”行反映了问题中的行。根据对这个答案的注释,您需要确保您的查询在语法上是正确的,不管您正在运行哪个版本的 SQL。

在 ID 字段递增并从1开始的简单情况下,示例中的行可以是:

INSERT INTO table_B(ID, VAL) VALUES(ID, VAL) FROM table_A WHERE ID=i;

将“选择计数”行替换为

SET n=10;

Will let you test your query on the first 10 record in table_A only.

最后一件事。这个过程也非常容易在不同的表之间嵌套,并且是我可以在一个表上执行一个过程的唯一方法,这个过程动态地将来自父表的每一行的不同数量的记录插入到一个新表中。

如果你需要它运行得更快,那么一定要设置它的基础,如果没有,这是罚款。 你也可以用光标的形式重写上面的内容,但是不一定能提高性能。例如:

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;
;;

请记住将要使用的变量声明为与查询表中的变量相同的类型。

我的建议是尽可能使用基于集的查询,必要时只使用简单的循环或游标。

    Use this:


$stmt = $user->runQuery("SELECT * FROM tbl WHERE ID=:id");
$stmt->bindparam(":id",$id);
$stmt->execute();


$stmt->bindColumn("a_b",$xx);
$stmt->bindColumn("c_d",$yy);




while($rows = $stmt->fetch(PDO::FETCH_BOUND))
{
//---insert into new tble
}

紫先生的例子,我用在 mysql 触发器这样,

begin
DECLARE n INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
Select COUNT(*) from user where deleted_at is null INTO n;
SET i=0;
WHILE i<n DO
INSERT INTO user_notification(notification_id,status,userId)values(new.notification_id,1,(Select userId FROM user LIMIT i,1)) ;
SET i = i + 1;
END WHILE;
end