我一直在寻找最后一小时左右,并没有找到这个看似简单问题的确凿答案:
如何调用存储的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 ;
仅作为一个例子。我也可以使用存储函数。
答案 0 :(得分:18)
这不能直接完成,因为存储过程中无界选择的输出是发送到客户端的结果集,但技术上不是表。
解决方法是让proc在为您创建表后将数据放入临时表中。此过程完成后,此表仅适用于您的连接。如果其他人同时运行proc并且任何其他连接都不可见,则不会导致冲突。
将此添加到程序:
DROP TEMPORARY TABLE IF EXISTS foo;
CREATE TEMPORARY TABLE foo SELECT ... your existing select query here ...;
当您的程序完成后,SELECT * FROM foo;
将为您提供您从proc获得的内容。您可以像任何桌子一样加入它。
当你完成后,丢弃它,或者当你断开连接时它会自行消失。如果再次运行proc,它将被删除并重新创建。
答案 1 :(得分:1)
根据@ Michael-sqlbot的建议,这是MySql 8中的一个具体示例:
function replaceAfter3Clicks(elem, newElem) {
let count = 0;
let callback = function() {
count++;
if (count >= 3) {
elem.replaceWith(newElem);
}
}
ins1.click(callback);
}
const ins1 = $("ins[data-ad-slot]");
// pre-made second ins for future replacement
const ins2 = document.createElement('ins');
ins2.?? = '9020596432';
ins2.innerText = 'ins2';
replaceAfter3Clicks(ins1, ins2);
哪个会产生:
-- 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's 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's usable
select * from tmpSomedata ;
答案 2 :(得分:0)
甚至更好的解决方案是在存储过程之外创建临时表,并使过程仅对其进行更新/插入。这样,可以将多次调用的结果存储在一个表中(只要插入了相同的列),最后使用简单的SELECT
进行检索。
以下是使用与上述#sinecospi相同的数据的示例:
/* The data */
drop table if exists someData ;
create table someData (itemId int, itemName varchar(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);
/* The stored procedure */
DROP PROCEDURE IF EXISTS sproc;
DELIMITER //
CREATE PROCEDURE sproc(
IN fld CHAR(64),
IN tbl CHAR(64)
)
BEGIN
SET @s = CONCAT('INSERT INTO results
SELECT \'',fld,'\' AS fld, x.* FROM (
SELECT ',fld,' AS bin, COUNT(',fld,') AS ct
FROM ',tbl,'
GROUP BY bin
ORDER BY bin) x;');
PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
/* Calls */
CREATE TEMPORARY TABLE IF NOT EXISTS results (
fld VARCHAR(30), bin VARCHAR(30), ct FLOAT);
CALL sproc('itemQty','someData');
CALL sproc('itemCat','someData');
SELECT * FROM results;
最后,临时表results
的输出为2个调用。