一尘不染

为MySQL中查询返回的每一行调用一个存储过程

mysql

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

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

我想我只是想让MySQL回答这个问题,但我对光标的理解却不够好:如何为查询返回的每一行执行一次存储过程?


阅读 390

收藏
2020-05-17

共1个答案

一尘不染

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

例如,如果testProc要调用的过程使用给定的方法id作为另一个表的查找键,则可以(并且应该)JOIN将表简单地组合在一起,例如:

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

仅在极少见的情况下,您不能以声明的方式表达您的问题,然后才应诉诸程序地解决问题。存储 过程
是在MySQL中执行过程代码的唯一方法。因此,您要么需要修改现有的存储过程,以使其在循环内执行其当前逻辑,要么创建一个新的存储过程,以从循环内调用现有的存储过程:

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
2020-05-17