2010-04-02 130 views
24

我已經看過有關此問題的Stack Overflow的其他問題,但他們都沒有清楚地回答這個問題。使用SQL來過濾存儲過程的結果

我們有一個名爲sp_who2的系統存儲過程,它返回服務器上所有正在運行的進程的信息結果集。我想過濾存儲過程返回的數據;從概念上講,我可能會這樣做:

SELECT * FROM sp_who2 
WHERE login='bmccormack' 

該方法雖然不起作用。實現查詢存儲過程返回數據的目標的最佳做法是什麼,最好不必查看原始存儲過程的代碼並對其進行修改。

回答

27

沒有好的方法來做到這一點。這是存儲過程的限制。您的選項有:

  1. 將程序切換到User Defined Function。在今天的世界上,人們正在制定應該是功能的存儲過程。這是一個教育問題。你的情況就是一個很好的例子。如果你的程序是不是一個UDF,你可能只是做到以下幾點,完全按照自己的直覺地認爲你應該能夠:

    SELECT * FROM udf_who2() 
    WHERE login='bmccormack' 
    
  2. 如果你真的不能碰你的程序,並必須有這個在SQL中完成,那麼你將不得不時髦。使另一個存儲過程來包裝您的原始過程。在新過程中調用現有過程並將值放入臨時表中,然後使用所需過濾器對該表運行查詢,並將結果返回給外部世界。

從SQL Server 2005開始,用戶定義的函數就是封裝數據檢索的方式。存儲過程以及視圖是在特定情況下使用的專業工具。他們在正確的時間都非常方便,但不是第一選擇。有些人可能會認爲上面的例子(A)獲得了該函數的所有結果,然後(B)對該結果集進行過濾,就像子查詢一樣。 情況並非如此。 SQL Server 2005+優化該查詢;如果在login上有索引,則在查詢執行計劃中看不到表掃描;非常有效。

編輯:我應該補充一點,UDF的內臟類似於SP的內臟。如果它與您想要避免的SP的邏輯混淆,您仍然可以將其更改爲函數。有幾次,我採取了大量可怕的程序代碼,我不想理解,併成功將其轉換爲函數。唯一的問題將是如果程序修改除了返回結果之外; UDF不能修改數據庫中的數據。

+0

需要提醒的是有潛在的內聯表值函數和多語句表值函數之間有很大的區別。內聯TVF可以像視圖一樣進行優化,並且它們對(參數化)視圖的行爲要比對函數的行爲要密切得多。 – 2010-04-03 11:10:11

+0

@Case Roux非常好的一點!如果它是一個多語句函數,選項1將增加簡單性,但可能不會提高性能。對於大量的行,可能是一條狗。如果性能很重要,選項2可能會更快。一如既往地依賴於這種情況。 – 2010-04-03 13:41:51

+0

如果存儲過程使用臨時表,這可能不起作用。 由於用戶定義的函數不能創建臨時表。 – yucer 2014-11-10 10:21:25

2

將數據放在Table變量或Temp表中並對其進行過濾。

+3

如何,請加一個例子,由於 – Mathematics 2015-09-14 09:48:50

9

你可以做一個OPENROWSET(),但也有一些安全/性能問題。

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

傳統上,將其添加到臨時變量/表將工作。

7

過濾臨時表是可能的方法。

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