2

SQL Server 2005 を使用してページ検索ストアド プロシージャを作成しました。多数のパラメータが必要で、検索条件はやや複雑です。

フロントエンド アーキテクチャのため、実際に結果を返さに返される結果の数を返せるようにする必要があります。次に、フロントエンドはストアド プロシージャを 2 回呼び出して、実際の結果を取得します。

一方では、2 つのストアド プロシージャを記述できます。1 つはカウントを処理し、もう 1 つは実際のデータを処理しますが、少なくとも 2 つの異なる場所で検索ロジックを維持する必要があります。別の方法として、ストアド プロシージャを記述して、ビット パラメーターを受け取り、それに基づいてデータまたはカウントのみを返すようにすることもできます。おそらく、一時テーブルにデータを入力し、それがカウントの場合はそこからカウントするだけで、そうでない場合はそこから選択します。ここでの問題は、カウント プロセスが最適化される可能性があるため、余分なオーバーヘッドが発生する可能性があることです (不要な列を取得する必要があるなど)。また、ストアド プロシージャでこの種のロジックを使用すると、2 つの使用の間を行き来するため、不適切なクエリ プランが発生する可能性があります。

システム内のデータ量はそれほど多くありません (より大きなテーブルでも数百万行のみ)。ただし、多くの同時ユーザーが存在する場合があります。

これらのアプローチに対する人々の考えは何ですか?私が思いもよらなかった方法でこの問題を解決した人はいますか?

1 回の呼び出しで結果とカウントを同時に取得することはできません。

ありがとう!

4

6 に答える 6

4

私は個人的に 2 つのクエリ アプローチを採用しています。そうです、検索ロジックを 2 つの場所で維持する必要があります。

単一のプロシージャに渡されるフラグを使用することは潜在的な解決策ですが、特に複雑な検索ロジックの場合、維持するのが非常に難しいと思います。

一時テーブルなどを使用するルートは、必要以上のオーバーヘッドを追加するだけです。

したがって、なぜ2つのクエリメソッドにたどり着いたのですか。私がオンラインで見つけたものはすべて、このアプローチも推奨しています。

于 2008-11-03T15:53:33.670 に答える
2

あなたはこれを考慮したと確信しています:データがCOUNTを変更していて、その後の実際のページングが異なる可能性がある場合(行が追加/削除された場合)

一致する行のPKを返すユーザー定義関数を使用できます。これは、比較的簡単に実行できます。

SELECT COUNT(*)FROM dbo.MyQueryFunction(@ Param1、@ Param2)

カウントを取得し、次に

CO1、Col2、..を選択します。
FROM dbo.MyQueryFunction(@ Param1、@ Param2)AS FN
     dbo.MyTableASTに参加する
         ON T.ID = FN.ID
     ...その他の参加..。

データを取得します。

これが後続のページングのRow_Numberとどの程度一致するかはわかりませんが、MyQueryFunction内に含まれる実際の「クエリロジック」は保持されます。Sprocで重複して取得される列のすべてのJOINが保持されます。関数。

于 2009-11-10T16:32:46.373 に答える
2

これは通常の問題ではなく、通常、ページを取得すると同時に合計数が必要になります。

つまり、2 つの異なる手順を使用します。その理由は、表面的にしか似ていない 2 つの非常に異なるアクションがあるためです。

于 2008-11-03T15:52:50.487 に答える
1

特定の問題には役立たないかもしれませんが、SQL 2005 では、ページング チェックに便利な Row_Number 関数が導入されています。

行番号の例

一時テーブルよりもはるかに簡単です。

于 2008-11-03T15:55:39.797 に答える
1

このスレッドが別のことを調査しているのを見つけたので、1 つのクエリで結果セットとレコード数を返すことが可能であることに言及したいと思います。値を運ぶには「out」パラメータが必要です。以下は Oracle の例をコピーして貼り付けたものですが、その手法は SQL Server の場合と非常によく似ています (SQL Server atm にアクセスできません)。

SQL Server の重要な点は、row_number() と rownum を使用する必要がある場合があることです。

procedure get_sample_results (
    startrow in number default 1,
    numberofrows in number default 10,
    whereclause in varchar2,
    matchingrows out number,
    rc  out sys_refcursor
)
is
    stmnt varchar2(5000);
    endrow number;
begin

    stmnt := stmnt || 'select * from table t where 1=1';
    if whereclause is not null then
        stmnt := stmnt || ' and ' || whereclause;
    end if;

    execute immediate 'select count(*) from (' || stmnt || ')' into matchingrows;

    stmnt := 'select * from (' || stmnt || ') where rownum between :1 and :2';        

    -- must subtract one to compenstate for the inclusive between clause
    endrow := startrow + numberofrows - 1;
    open rc for stmnt using startrow, endrow;

end get_sample_results;
于 2009-11-10T16:05:26.623 に答える
0

これは古い質問 (既にマークされています) であることは知っていますが、レコードセット (別名、結果) を返すことができ、出力 (または複数の出力) 値を持つことができます。これは、データベースへの往復が 1 回だけで済むことを意味します。

これは私が大声で考えていることです(そして、それは私の就寝時間を過ぎています...)

CREATE PROCEDURE WhatEver
(
   @SomeParam1 NVARCHAR(200),
   ....
   @SomeParam_X INT,
   @NumberOfResults INTEGER OUTPUT
)
BEGIN
    SET NOCOUNT ON

    -- Do your search stuff.
    -- ....
    SELECT Whatever
    FROM WhatWhat
    ...

    -- Ok, the results/recordset has been sent prepared.
    -- Now the rowcount
    SET @NumberOfResults = @@ROWCOUNT
END

HTH。

于 2010-11-15T13:17:10.977 に答える