Для дальнейшего использования, если кто-то может найти это полезным, вот суть решения, которое я придумал:
CREATE STORED PROCEDURE sp_panel_breakdown(p_panel_id INT)
BEGIN
-- create temporary table
DROP TABLE IF EXISTS breakdown;
CREATE TEMPORARY TABLE breakdown(breakdown_id INT NOT NULL AUTO_INCREMENT, assembly_id INT, cost1 DECIMAL(10,2), cost2 DECIMAL(10,2), ..., cost10 DECIMAL(10,2), PRIMARY KEY (breakdown_id));
-- insert data into temporary table
SELECT sf_assembly_breakdown(assembly_id) as dummy
FROM assembly
WHERE panel_id=p_panel_id;
-- return temporary table
SELECT * FROM breakdown;
END
CREATE STORED FUNCTION sf_assembly_breakdown(p_assembly_id INT) RETURNS INT
BEGIN
-- do cost calculations
...
-- insert calculated costs as a new row in temporary table
INSERT INTO breakdown SELECT null, p_assembly_id, cost1, cost2, ..., cost10;
-- return dummy value
RETURN null;
END
Ключевые моменты:
1) sp_assembly_breakdown
был преобразован из хранимой процедуры в хранимую функцию. Это позволяет вызывать его для каждой строки в запросе SELECT в родительской процедуре sp_panel_breakdown
.
2) sp_assembly_breakdown
, вместо того, чтобы возвращать набор результатов из одной строки, теперь вставляет одну строку во временную таблицу. Таким образом, результаты могут быть собраны для каждого последующего вызова функции. Кроме того, функция возвращает пустое значение, потому что она должна что-то возвращать.
3) Родительская процедура sp_panel_breakdown
должна создать временную таблицу breakdown
для использования в sf_assembly_breakdown
.
4) Первый запрос выбора внутри sp_panel_breakdown
вызывает функцию sf_assembly_breakdown
FOR EACH ROW. Это возвращает 1-й «фиктивный» набор результатов.
5) Наконец, процедура sp_panel_breakdown
возвращает все содержимое временной таблицы breakdown
в качестве 2-го набора записей.
6) При вызове sp_panel_breakdown
возвращаются 2 набора результатов. 1-й набор результатов содержит фиктивные нулевые значения, 2-й набор результатов содержит содержимое временной таблицы breakdown
.