如何遍历表格的所有行? (MySQL的)

时间:2011-04-28 10:48:20

标签: mysql loops

我有一个表A,并且有一个主键ID。

现在我想浏览A中的所有行。

我发现'对于A中的每个记录都有',但这似乎不是你在MySQL中的表现。

对于我想要获取字段并对其进行转换的每一行,将其插入到另一个表中,然后更新某些行的字段。我可以将select部分和插入放在一个语句中,但我不知道如何在那里获得更新。所以我想循环。而对于练习,我不想使用除MySQL之外的任何东西。

修改

我很感激一个例子。

并且不需要将其纳入程序中。

编辑2

好的想想这个场景:

表A和B,每个都有字段ID和VAL。

现在这是我想要做的伪代码:

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

基本上使用循环将A的内容复制到B中。

(这只是一个简化的例子,当然你不会为此使用循环。) }

5 个答案:

答案 0 :(得分:97)

由于循环的建议意味着请求过程类型解决方案。这是我的。

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

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 ;

并运行新程序

CALL ROWPERROW();

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

请注意,此处使用的“INSERT INTO”行反映了问题中的行。根据对此答案的评论,您需要确保您的查询在语法上对于您正在运行的SQL版本是正确的。

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

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

替换“SELECT COUNT”行
SET n=10;

只允许您在table_A中的前10条记录上测试您的查询。

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

如果你需要它运行得更快,那么一定要尝试设置它,如果没有那么这很好。 您也可以用光标形式重写上述内容,但可能无法提高性能。例如:

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

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

我的建议是尽可能使用基于setbased的查询,如果必须,只使用简单的循环或游标。

答案 1 :(得分:12)

您应该使用基于集合的解决方案,包含两个查询(基本插入):

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

现在,如果你的转换比那个更复杂并涉及多个表,请发布另一个带有详细信息的问题。

答案 2 :(得分:4)

CURSORS是一个选项,但通常不赞成,因为它们通常不能充分利用查询引擎。考虑调查“基于SET的查询”,看看是否可以在不使用CURSOR的情况下实现您想要做的事情。

答案 3 :(得分:0)

我在mysql触发器中使用过的Purple先生的例子,

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

答案 4 :(得分:-17)

    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
    }