Как использовать вывод таблицы из хранимой процедуры MYSQL
Я искал последний час или около того и не нашел убедительного ответа на эту, казалось бы, простую проблему:
Как вы вызываете хранимую функцию/процедуру MYSQL и используете ее вывод в последующих запросах SELECT?
Хотя это, очевидно, не работает, это то, что я хотел бы иметь:
SELECT P.`id` FROM (CALL test_proc()) AS P
Где test_proc() определяется следующим образом:
DROP PROCEDURE IF EXISTS test_proc;
DELIMITER ;;
CREATE PROCEDURE test_proc()
BEGIN
SELECT * FROM `table`;
END;;
DELIMITER ;
Как пример. Мне было бы неплохо использовать хранимую функцию.
Ответы
Ответ 1
Это невозможно сделать напрямую, поскольку вывод неограниченного выбора в хранимой процедуре - это набор результатов, отправленный клиенту, но не технически таблица.
Обходной путь заключается в том, чтобы позволить proc поместить данные во временную таблицу после создания таблицы для вас. Эта таблица будет доступна только для вашего соединения, когда процедура завершится. Это не вызовет конфликта, если кто-то еще запускает proc в одно и то же время и не будет видимым для какого-либо другого соединения.
Добавьте это в процедуру:
DROP TEMPORARY TABLE IF EXISTS foo;
CREATE TEMPORARY TABLE foo SELECT ... your existing select query here ...;
Когда ваша процедура закончится, SELECT * FROM foo;
предоставит вам то, что вы получили от proc. Вы можете присоединиться к нему почти так же, как и любой стол.
Когда все будет готово, отбросьте его, или он исчезнет сам по себе, когда вы отключитесь. Если вы снова запустите proc, он будет сброшен и воссоздан.
Ответ 2
Вот конкретный пример в MySql 8, основанный на предложении @Michael-sqlbot:
-- Create some test data
drop table if exists someData ;
create table someData (itemId int, itemName varcharacter(20), itemQty int, itemCat int) ;
insert into someData values
(1,'First', 9, 1)
,(2,'Second',50, 3)
,(3,'Third', 12, 5)
,(4,'Fourth', 7, 3)
,(5,'Fifth', 1, 2)
,(6,'Sixth', 1, 1)
,(7,'Seventh', 9, 3)
,(8,'Eighth', 0, 2)
;
-- Just checking that it all there!
select * from someData ;
-- Define the proc
delimiter //
drop procedure if exists prcSomeData //
create procedure prcSomeData()
comment 'Create a temporary table called "tmpSomeData"'
begin
drop table if exists tmpSomeData ;
create temporary table tmpSomeData as
select itemCat
, sum(itemQty) as 'itemsTot'
, min(itemQty) as 'lowestQty'
, max(itemQty) as 'highestQty'
from someData
group by itemCat
order by itemCat
;
end //
delimiter ;
-- Gotta run the proc to instantiate the temp table
call prcSomeData() ; -- produces a temporary table "tmpSomeData", exists for the session
-- Now it usable
select * from tmpSomedata ;
Который производит:
itemCat|itemsTot|lowestQty|highestQty|
-------|--------|---------|----------|
1| 10| 1| 9|
2| 1| 0| 1|
3| 66| 7| 50|
5| 12| 12| 12|