27

我想要一个有效的 MySQL 存储过程:

foreach id in (SELECT id FROM objects WHERE ... ) CALL testProc(id)

我想我只是想要 MySQL 回答这个问题,但我不太了解游标:如何为查询返回的每一行执行一次存储过程?

4

1 回答 1

44

“循环”(for-each、while 等)和“分支”(if-else、call 等)等概念是过程性的,在SQL 等声明性语言中不存在。通常人们可以用声明的方式表达自己想要的结果,这将是解决这个问题的正确方法。

例如,如果testProc要调用的过程将给定的值id用作另一个表的查找键,那么您可以(并且应该)JOIN将表简单地放在一起——例如:

SELECT ...
FROM   objects JOIN other USING (id)
WHERE  ...

只有在极少数情况下,您的问题无法以声明方式表达,您才应该诉诸程序解决问题。存储过程是在 MySQL 中执行过程代码的唯一方法。因此,您要么需要修改现有的 sproc 以便它在循环中执行其当前逻辑,要么创建一个新的 sproc 来从循环中调用现有的:

CREATE PROCEDURE foo() BEGIN
  DECLARE done BOOLEAN DEFAULT FALSE;
  DECLARE _id BIGINT UNSIGNED;
  DECLARE cur CURSOR FOR SELECT id FROM objects WHERE ...;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE;

  OPEN cur;

  testLoop: LOOP
    FETCH cur INTO _id;
    IF done THEN
      LEAVE testLoop;
    END IF;
    CALL testProc(_id);
  END LOOP testLoop;

  CLOSE cur;
END
于 2013-01-14T22:32:40.007 回答