web-dev-qa-db-ja.com

行がある場合のみ、ストアドプロシージャからレコードセットを返す

アプリケーションで使用する複数のレコードセットを返すストアドプロシージャがあります。時々それらのレコードセットのいくつかは空です。

オーバーヘッドを減らして、1行以上の行のみを返したいのですが。

私の質問は-行を持つレコードセットのみを返すにはどうすればよいですか?

アプリケーションは単に0個以上のレコードセットを予期し、それぞれをループしてそれらを出力します。

アプリケーションコードでそれらをスキップできることはわかっていますが、空の場合は返されないようにしています。

手順は次のように簡単です。

CREATE PROCEDURE bfsp_PROC_NM
AS 

    BEGIN

        SELECT * FROM TABLE_1

        SELECT * FROM TABLE_2

        SELECT * FROM TABLE_3

        RETURN  

    END
GO

実際の手順では、一部のクエリは負荷が高いため、クエリをテストする必要がないので、1つ以上の行が返された場合は再度実行します。高すぎるためです。

3
GWR

アプリケーションで使用する複数のレコードセットを返すストアドプロシージャがあります。時々それらのレコードセットのいくつかは空です。

オーバーヘッドを減らして、1行以上の行のみを返したいのですが。

それはひどい考えです。アプリケーションは、処理している結果セットをどのようにして知るのですか?ストアドプロシージャには、結果セットの図形の固定セットが必要です。

そうは言っても、これを行うには結果を一時テーブルにロードし、空でない場合はそれらからSELECTします。

例えば

CREATE PROCEDURE bfsp_PROC_NM
AS 

    BEGIN
        SELECT * 
        into #result1
        FROM TABLE_1
        if @@rowcount > 0
          select * from #result1

        SELECT * 
        into #result2
        FROM TABLE_2
        if @@rowcount > 0
          select * from #result2

        SELECT * 
        into #result3
        FROM TABLE_3
        if @@rowcount > 0
          select * from #result3

    END
GO

私は自分のコードが予測可能であることを望んでいます。常にX組のデータを返す場合は、それをアプリケーションでプログラムでき、何を期待するかを常に知っています。したがって、セットを除外することは、おそらく最善のアイデアではありません。

ただし、オプションは、実行しているテーブル/選択が行を返すかどうかをチェックし、行がセットを返すかどうかをチェックし、それ以外の場合はスキップします。返されるすべての結果セットに対して指定する必要があるため、これには明らかに少しオーバーヘッドがあります。

このコードに見られる例:

CREATE TABLE dbo.ReturnSet1( Id INT IDENTITY,NickName VARCHAR(256) )
CREATE TABLE dbo.ReturnSet2 (Id INT IDENTITY,NickName VARCHAR(256) )

INSERT INTO ReturnSet1
VALUES('TestRecord')

GO
CREATE PROCEDURE dbo.TestReturnSet
AS
BEGIN

    IF EXISTS ( SELECT 1 FROM dbo.ReturnSet1 )
    BEGIN
        SELECT NickName
         FROM dbo.ReturnSet1
    END

    IF EXISTS ( SELECT 1 FROM dbo.ReturnSet2 )
    BEGIN
        SELECT NickName
         FROM dbo.ReturnSet2
    END


END
GO

EXEC dbo.TestReturnSet

DROP TABLE dbo.ReturnSet1
DROP TABLE dbo.ReturnSet2
DROP PROCEDURE dbo.TestReturnSet
4
Yannick Liekens

3つのテーブルすべてのデータが同様の構造であると想定すると、データを単一の一時テーブルに挿入して、使用可能なすべての行を含む1つの結果セットをプロシージャに返すことができます。

create procedure one_result_set

    # create temp table to hold all result rows
    create temporary table temp_one {
        table_name char(50),  # this field indicates source table
        field1 type1,
        ...
        fieldN typeN
    }

    # insert rows from first table into temp table 
    insert into temp_one
    select 'table1', t.* from table1 t;

    # insert rows from second table into temp table 
    insert into temp_one
    select 'table2', t.* from table2 t;

    # insert rows from third table into temp table 
    insert into temp_one
    select 'table3', t.* from table3 t;

    # finally, return all the fetched rows as a single result set
    select * from temp_one;

end procedure$$

返される結果セットは空である可能性があります-3つのソーステーブルのいずれにも返すべきデータがなかった場合-しかし、これはメタデータから判断できます。

ソーステーブルしないでくださいが同様の構造を共有する場合、以前の応答に同意する必要があります-可変数の結果セットを返すことは悪い考えですソーステーブルが異なり、プロシージャが返す結果セットが3つ未満の場合は、各結果セットのフィールドリストを確認して、データを処理する前に欠落しているものを把握する必要があります。

1
Sam