Подтвердить что ты не робот

Вызовите хранимую процедуру для каждой строки, возвращаемой запросом в MySQL

Мне нужна хранимая процедура MySQL, которая эффективно выполняет:

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

Я думаю, что просто хочу, чтобы MySQL ответил на этот вопрос, но я плохо понимаю курсоры: Как выполнить хранимую процедуру один раз для каждой строки, возвращаемой запросом?

4b9b3361

Ответ 1

Такие понятия, как "циклы" (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