如何使用存储的MYSQL过程中的表输出

时间:2013-07-30 10:43:57

标签: mysql select stored-procedures stored-functions

我一直在寻找最后一小时左右,并没有找到这个看似简单问题的确凿答案:

如何调用存储的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 ;

仅作为一个例子。我也可以使用存储函数。

3 个答案:

答案 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个调用。