web-dev-qa-db-ja.com

SQLを使用してストアドプロシージャの結果をフィルター処理する

Stack Overflowでこの質問に関連する他の質問を見ましたが、どれもこの質問に明確に回答するようには見えませんでした。

サーバーで実行中のすべてのプロセスに関する情報の結果セットを返すsp_who2というシステムストアドプロシージャがあります。ストアドプロシージャから返されたデータをフィルター処理したいのですが、概念的には、次のようにすることができます。

SELECT * FROM sp_who2
WHERE login='bmccormack'

ただし、その方法は機能しません。できれば元のストアドプロシージャのコードを調べて変更することなく、ストアドプロシージャの返されたデータをクエリするという目標を達成するための良い方法は何ですか。

35
Ben McCormack

それを行う良い方法はありません。これは、ストアード・プロシージャーの制限です。オプションは次のとおりです。

  1. プロシージャを ユーザー定義関数 に切り替えます。今日、世界中で人々は関数であるべきストアドプロシージャを作っています。それは教育の問題です。あなたの状況がその良い例です。手順が代わりにUDFである場合は、次のことを実行できます。

    SELECT * FROM udf_who2()
    WHERE login='bmccormack'
    
  2. あなたが本当にあなたの手順に触れることができず、そしてmustこれをSQLで行わなければならない場合、ファンキーになる必要があります。別のストアドプロシージャを作成して、元のプロシージャをラップします。新しいプロシージャの内部で既存のプロシージャを呼び出し、値を一時テーブルに入れてから、必要なフィルタを使用してそのテーブルに対してクエリを実行し、その結果を外部に返します。

SQL Server 2005以降、ユーザー定義関数は、データ取得をカプセル化する方法です。ストアドプロシージャは、ビューと共に、特定の状況で使用する特殊なツールです。どちらも適切なタイミングで非常に便利ですが、最初の選択肢ではありません。上記の例では、(A)関数のすべての結果を取得し、次に(B)サブクエリのように、その結​​果セットにフィルターをかけると考える人もいます。 これはそうではありません。 SQL Server 2005+はそのクエリを最適化します。 loginにインデックスがある場合、クエリ実行プランにテーブルスキャンは表示されません。非常に効率的です。

Edit:UDFの内部はSPの内部と似ていることを付け加えておきます。回避したいSPのlogicに干渉している場合でも、関数に変更できます。私が理解したくなかった、大きくて怖い手順コードを取り、それを関数に正常に転送しました。唯一の問題は、手順が変更に加えて結果; UDFはデータベース内のデータを変更できません。

33
Patrick Karcher

一時テーブルのフィルタリングが可能な方法です。

-- Create tmp table from sp_who results
CREATE TABLE #TmpWho
(spid INT, ecid INT, status VARCHAR(150), loginame VARCHAR(150),
hostname VARCHAR(150), blk INT, dbname VARCHAR(150), cmd VARCHAR(150), request_id INT)
INSERT INTO #TmpWho
EXEC sp_who

-- filter temp table where spid is 52
SELECT * FROM #TmpWho
WHERE spid = 52

DROP TABLE #TmpWho
19
Petr Dostál

OPENROWSET()を実行できますが、セキュリティ/パフォーマンスの問題がいくつかあります。

SELECT * 
FROM OPENROWSET ('SQLOLEDB', 'Server=(local);TRUSTED_CONNECTION=YES;', 'exec mystoredproc')

伝統的に、それを一時変数/テーブルに追加することで機能します。

12
bryanjonker

データをTable変数またはTempテーブルに配置し、フィルターします。

3
Fahad

OPENROWSET()は方法です:

SELECT *
FROM
    OPENROWSET('SQLNCLI', 'Server=(local);TRUSTED_CONNECTION=YES;', 'exec sp_who')
WHERE loginame = 'test' AND dbname = 'Expirement';

また、作業する前に事前構成を有効にする必要があります。

sp_configure 'show advanced options', 1;  
RECONFIGURE;
GO
sp_configure 'Ad Hoc Distributed Queries', 1; 
RECONFIGURE;
GO 
1
Lei Chi