2017-10-11 21 views
0

簡単にするために、ストアドプロシージャ内で動的に作成されるセットを返したいとします。ループ内で計算されます)。MySQLストアドプロシージャから一度に複数の行を返す方法

ので、同様に私が働いてきたいくつかのデータベースは、プロシージャの結果セットにOUTパラメータの現在の値を追加SUSPEND手術をした:

DELIMITER $ 

CREATE PROCEDURE EvenNumbers(
    IN n INT, OUT NUM INT) 
BEGIN 
    DECLARE i INT DEFAULT 0; 
    WHILE i < n DO 
     SET NUM = i; 
     SUSPEND; /* adds a row with a value 'i' for column NUM to the result set */ 
     SET i = i+2; 
    END WHILE; 
END$ 

DELIMITER ; 

SUSPENDは、MySQLのキーワードですが、私これは動作しないので同じことをしないと仮定します(Error: Unexpected 'SUSPEND')。

MySQLのストアドプロシージャから行のセットを1つずつ返すにはどうすればよいですか?

+0

「一度に1つ」というようなものはありません。ストアドプロシージャが完了して実行され、結果が得られます。それらの結果をクライアントにストリーミングする場合は、それがあなたのものです。 – tadman

+0

@tadmanプロシージャの最後に結果をどこかに格納してクライアントに返すのは問題ないですが、MySQLでどのように行うのかわかりません(一時的なテーブルを除いても、 。 – Alex

答えて

1

偶数番号ジェネレータが必要ですか? これはストアドプロシージャを使用せずに純粋なMySQLです。

まず、以下のクエリで多数の数字を生成する必要があります。 このクエリは、1〜10000のレコードを生成します。

クエリ

SELECT 
    @row := @row + 1 AS ROW 
    FROM 
    (
    SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
) row1 
    CROSS JOIN (
    SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
) row2 
    CROSS JOIN (
    SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
) row3 
    CROSS JOIN (
    SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
) row4 

    CROSS JOIN (
    SELECT @row := 0 
) init_user_param 

メインクエリ。

クエリ

SELECT 
* 
FROM (

    SELECT 
    @row := @row + 1 AS ROW 
    FROM 
    (
    SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
) row1 
    CROSS JOIN (
    SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
) row2 
    CROSS JOIN (
    SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
) row3 
    CROSS JOIN (
    SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
) row4 

    CROSS JOIN (
    SELECT @row := 0 
) init_user_param 

) 
ROWS 
WHERE 
    ROWS.ROW BETWEEN 1 AND 10 
AND 
    ROWS.ROW MOD 2 = 0 

結果

row 
-------- 
     2 
     4 
     6 
     8 
     10 
+0

ありがとうございますが、偶数は単なる例でした。私はループ内の複雑な計算によって返される各行が決定される一般的なソリューションを探しています。 – Alex

1

アレックス、 あなたは計算の結果を格納し、(完全にOKです)ストアド・プロシージャ内で一時テーブルを作成することができますそれを計算したら、一時テーブルの内容を返します。したがって、OUTパラメーターの代わりに、プロシージャーから戻される通常の結果セットを使用してください。

+0

私はそれをやってしまいましたが、一時的なテーブルを削除しても後続の呼び出しでエラーが発生しないように思われますが、テーブルの名前空間を汚染します(同じテーブル名が同じデータベース内のどこでも使用されます)。 MySQLには、ローカルのTABLE変数が必要です。 – Alex

+0

「一時表の作成」を使用すると、表の名前空間の汚染はありません。一時テーブルを使用すると、接続内で一意であり、接続が閉じられるか、ドロップするまで存続します。物事を安全にするために、一時テーブルを作成する前に「一時テーブルmy_tmpを削除する」を実行するか、手順の最後に「一時テーブルmy_tmpを削除する」を実行します。 – slaakso

+0

'create temporary table'を使うと、現在の接続*のコンテキストの外にあるテーブル名前空間*の汚染はありません。私はまだ私の一時テーブルに使用する名前がどこにも使用されていないことを確認する必要があります。さらに、誰かが別のテーブルに同じ名前を後で使用することにした場合、ストアドプロシージャが実行されたときにだけエラーが表示されるため、他のすべての人がその決定を認識しなければなりません。全体的に、一時テーブルソリューションは、プロシージャからの抽象リークです。プロシージャはもはや自己完結型ではありません。 – Alex

関連する問題