2009-09-29 120 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