2009-09-29 121 views
223

我有一個存儲過程返回行:SQL服務器 - 從存儲過程

CREATE PROCEDURE MyProc 
AS 
BEGIN 
    SELECT * FROM MyTable 
END 

我的實際過程是一個更復雜一點,這就是爲什麼一個存儲過程是必要的。

是否可以通過調用此過程來選擇輸出?

喜歡的東西:

SELECT * FROM (EXEC MyProc) AS TEMP 

我需要使用SELECT TOP XROW_NUMBER,和一個額外的WHERE子句頁我的數據,我真的不希望通過這些值作爲參數。

+0

我不確定你打算在這裏做什麼,因爲當你執行該過程,你正在返回行。難道你想在SELECT語句中執行這個過程,所以你可以將它綁定到一個可分頁的對象? – 2009-09-29 13:11:00

+1

爲什麼你不想將值作爲參數傳遞是否有特殊原因?要做到這一點,你建議的方式有點不夠 - 你會選擇比你需要的更多的數據,然後不使用它。 – 2009-09-29 13:13:51

+2

看看這裏:http://www.sommarskog.se/share_data.html – pylover 2012-05-09 10:51:17

回答

105

您可以使用User-defined functionview而不是過程。

過程可以返回多個結果集,每個結果集都有自己的模式。它不適合在SELECT聲明中使用。

+6

此外,如果轉換爲UDF後,您發現需要存儲過程語義,則始終可以使用過程包裝UDF。 – 2009-09-29 13:26:05

+0

如果我們需要發送參數給多個存儲過程並將它們合併成一個大的存儲過程呢?可以查看參數,像存儲過程一樣 – mrN 2011-08-18 07:14:04

+3

@mrN視圖不需要參數,但UDF可以。 – 2011-08-18 08:26:46

62

要麼你想要一個Table-Valued function或插入您的EXEC到一個臨時表:

INSERT INTO #tab EXEC MyProc 
+22

INSERT#T或INSERT @ T的問題是'INSERT EXEC'語句不能嵌套。 如果存儲過程已經有一個'INSERT EXEC',這將不起作用。 – MOHCTP 2013-05-30 01:44:46

117

可以

  1. 創建一個表變量來保存 結果從存儲過程和 設置,那麼
  2. 將 存儲過程的輸出插入表變量 然後
  3. 使用表變量 完全按照自己的任何其他 表...

... SQL ....

Declare @T Table ([column definitions here]) 
Insert @T Exec storedProcname params 
Select * from @T Where ... 
+22

「INSERT#T」或「INSERT @ T」的問題在於「INSERT EXEC」語句不能嵌套。 如果存儲過程已經有一個'INSERT EXEC',這將不起作用。 – MOHCTP 2013-05-30 01:44:46

+1

這可能是最接近基本SQL的最便攜的解決方案。它也有助於保持強大的列類型定義。應該有比以上更多的讚揚。 – 2014-08-08 18:58:39

+0

根據sp重新編譯,[table variables](https://www.simple-talk.com/sql/t-sql-programming/temporary-tables-in-sql-server/)看起來比臨時表更有用。所以我同意,這個答案應該有更多upvotes。 – resnyanskiy 2016-03-16 05:21:02

2

這聽起來像你可能只需要使用一個view 。視圖允許將查詢表示爲表格,以便查詢視圖。

18

您可以將輸出從sp複製到節奏表。

CREATE TABLE #GetVersionValues 
(
    [Index] int, 
    [Name] sysname, 
    Internal_value int, 
    Character_Value sysname 
) 
INSERT #GetVersionValues EXEC master.dbo.xp_msver 'WindowsVersion' 
SELECT * FROM #GetVersionValues 
drop TABLE #GetVersionValues 
127

你應該看看由厄蘭Sommarskog這個優秀的文章:

它基本上列出了你的方案中所有可用的選項。

+2

這應該是真正被接受的答案。所引用的文章非常詳盡。 – ssmith 2010-02-24 16:46:43

+1

很好的參考,我可以看到我很長一段時間回來。 – 2012-01-25 20:55:18

+0

優秀的答案,謝謝! – 2017-05-23 14:46:43

4

你可以騙一點與OPENROWSET:

SELECT ...fieldlist... 
FROM OPENROWSET('SQLNCLI', 'connection string', 'name of sp') 
WHERE ... 

這仍然運行在整個SP每一次,當然。

33

你必須瞭解OPENROWSETOPENQUERY

SELECT * 
INTO #tmp FROM  
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters') 
30

這是沒有必要使用臨時表。

這是我的解決方案

SELECT * FROM  
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters') 
WHERE somefield = anyvalue 
+1

這需要您將服務器作爲鏈接服務器添加到自身,但它的作用就像一個魅力!謝謝! – vaheeds 2016-11-16 09:42:51

+0

關於此的一些偉大的警告:http://stackoverflow.com/questions/2374741/why-is-using-openquery-on-a-local-server-bad – 2017-05-19 07:57:21

+0

嗯......我得到錯誤「錯誤7411:服務器'YourServerName'未配置爲數據訪問。「我需要改變什麼? – Matt 2017-12-05 09:21:55

2

嘗試將你的程序中以一個內聯函數如下返回一個表:

CREATE FUNCTION MyProc() 
RETURNS TABLE AS 
RETURN (SELECT * FROM MyTable) 

然後你就可以把它作爲

SELECT * FROM MyProc() 

您還可以選擇將參數傳遞給函數,如下所示:

CREATE FUNCTION FuncName (@para1 para1_type, @para2 para2_type , ...) 

,並調用它

SELECT * FROM FuncName (@para1 , @para2) 
14

您需要聲明含有相同數量的存儲過程將返回列的表型。在表類型的列和程序返回列的數據類型應該是相同的

declare @MyTableType as table 
(
FIRSTCOLUMN int 
,..... 
) 

然後,你需要在你剛纔定義

Insert into @MyTableType 
EXEC [dbo].[MyStoredProcedure] 
你的表類型插入您的存儲過程的結果

最終只是從你的表型

Select * from @MyTableType 
+0

這對我來說是最好的解決方案,因爲您不需要指定服務器名稱,連接字符串或必須配置任何鏈接的服務器才能使其工作 - 這是我不想做的事情獲取一些數據。謝謝!可怕的答案! – Matt 2017-12-05 09:27:21

5

使用OPENQUERY選擇並befor執行一套「SET FMTONLY OFF;設置NOCOUNT ON;'

試試這個示例代碼:

SELECT top(1)* 
FROM 
OPENQUERY([Server], 'SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE [database].[dbo].[storedprocedure] value,value ') 
0

如果您的服務器名爲SERVERX例如,我這是怎麼做的?

EXEC sp_serveroption 'SERVERX', 'DATA ACCESS', TRUE; 
DECLARE @CMD VARCHAR(1000); 
DECLARE @StudentID CHAR(10); 
SET @StudentID = 'STUDENT01'; 
SET @CMD = 'SELECT * FROM OPENQUERY([SERVERX], ''SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE MYDATABASE.dbo.MYSTOREDPROC ' + @StudentID + ''') WHERE SOMEFIELD = SOMEVALUE'; 
EXEC (@CMD); 

要檢查這個工作,我註釋掉EXEC()命令行並將其替換爲SELECT @CMD以在嘗試執行命令之前查看該命令!這是爲了確保所有正確數量的單引號在正確的位置。 :-)

我希望可以幫助別人。

2

如果訪問數據的「假,

EXEC sp_serveroption 'SQLSERVERNAME', 'DATA ACCESS', TRUE 

後,

SELECT * FROM OPENQUERY(SQLSERVERNAME, 'EXEC DBNAME..MyProc @parameters') 

它的工作原理。

1

爲了簡單,並使其重新運行的緣故,我使用了一個系統的StoredProcedure「sp_readerrorlog」獲得的數據:

-----USING Table Variable 
DECLARE @tblVar TABLE (
    LogDate DATETIME, 
    ProcessInfo NVARCHAR(MAX), 
    [Text] NVARCHAR(MAX) 
) 
INSERT INTO @tblVar Exec sp_readerrorlog 
SELECT LogDate as DateOccured, ProcessInfo as pInfo, [Text] as Message FROM @tblVar 



-----(OR): Using Temp Table 
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp; 
CREATE TABLE #temp (
    LogDate DATETIME, 
    ProcessInfo NVARCHAR(55), 
    Text NVARCHAR(MAX) 
) 
INSERT INTO #temp EXEC sp_readerrorlog 
SELECT * FROM #temp