web-dev-qa-db-ja.com

ストアドMYSQLプロシージャからのテーブル出力の使用方法

私は過去1時間ほど探していましたが、この一見単純な問題に対する決定的な答えは見つかりませんでした。

保存された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 ;

例として。ストアドファンクションを使用してもかまいません。

17
Johannes

ストアドプロシージャ内の無制限の選択の出力はクライアントに送信される結果セットですが、厳密にはテーブルではないため、これを直接行うことはできません。

回避策は、テーブルを作成した後、プロシージャがデータを一時テーブルに配置することです。このテーブルは、手順が終了したときに接続でのみ使用できます。他の誰かが同時にprocを実行し、他の接続から見えない場合でも、競合は発生しません。

これをプロシージャに追加します。

DROP TEMPORARY TABLE IF EXISTS foo;
CREATE TEMPORARY TABLE foo SELECT ... your existing select query here ...;

手順が終了したら、SELECT * FROM foo;は、プロシージャから取得したものを提供します。他のテーブルとほとんど同じように参加できます。

完了したら、それをドロップします。そうしないと、切断したときに自動的に消えます。もう一度procを実行すると、ドロップされて再作成されます。

20

@ Michael-sqlbotの提案に基づいたMySql 8の具体例を次に示します。

-- 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 ;

生成されるもの:

itemCat|itemsTot|lowestQty|highestQty|
-------|--------|---------|----------|
      1|      10|        1|         9|
      2|       1|        0|         1|
      3|      66|        7|        50|
      5|      12|       12|        12|
1
sinecospi