SQL Server - SELECT FROM存储过程

jon*_*ers 312 sql sql-server stored-procedures sql-server-2005

我有一个返回行的存储过程:

CREATE PROCEDURE MyProc
AS
BEGIN
    SELECT * FROM MyTable
END
Run Code Online (Sandbox Code Playgroud)

我的实际程序有点复杂,这就是为什么有必要使用sproc的原因.

是否可以通过调用此过程来选择输出?

就像是:

SELECT * FROM (EXEC MyProc) AS TEMP
Run Code Online (Sandbox Code Playgroud)

我需要使用SELECT TOP X,ROW_NUMBER和一个附加WHERE子句来分页我的数据,我真的不想将这些值作为参数传递.

Cha*_*ana 179

您可以

  1. 创建一个表变量来保存存储过程中的结果集然后
  2. 将存储过程的输出插入表变量,然后
  3. 完全像使用任何其他表一样使用表变量...

...... sql ....

Declare @T Table ([column definitions here])
Insert @T Exec storedProcname params 
Select * from @T Where ...
Run Code Online (Sandbox Code Playgroud)

  • `INSERT#T`或`INSERT @ T`的问题是`INSERT EXEC`语句不能嵌套.如果存储过程中已经有一个"INSERT EXEC",则不起作用. (29认同)
  • 这可能是最便携的解决方案,最接近基本SQL.它还有助于维护强列类型定义.应该有比上述更多的赞成. (2认同)

kri*_*tof 156

你应该看看Erland Sommarskog的这篇优秀文章:

它基本上列出了您的方案的所有可用选项.

  • @ssmith嗯,除了[答案的链接不是真正的答案,它们是答案的指示](https://meta.stackexchange.com/a/8259/184684).将这些信息移动到这个答案中会很棒,尤其是在博客作者允许的情况下. (17认同)
  • 这应该是公认的答案.引用的文章非常详尽. (2认同)

Meh*_*ari 144

您可以使用用户定义的函数视图而不是过程.

过程可以返回多个结果集,每个结果集都有自己的模式.它不适合在SELECT声明中使用.

  • 此外,如果转换为UDF后发现需要存储过程语义,则始终可以使用过程包装UDF. (8认同)
  • @mrN视图不接受参数,但UDF可以. (3认同)
  • 您好,我真的需要这样做而不将sp转换为视图或函数,是否可能? (3认同)
  • 虽然您的答案是真实的陈述,但它并没有回答问题....“SELECT FROM 存储过程”这肯定不是理想的,但它就是这样...@Aamir 的答案是正确的答案。无论是那个还是问题都需要改变……这对我来说似乎有点荒谬。 (2认同)

CMe*_*rat 73

您要么需要表值函数,要么将EXEC插入临时表:

INSERT INTO #tab EXEC MyProc
Run Code Online (Sandbox Code Playgroud)

  • `INSERT#T`或`INSERT @ T`的问题是`INSERT EXEC`语句不能嵌套.如果存储过程中已经有一个"INSERT EXEC",则不起作用. (30认同)

Riz*_*taz 41

您必须阅读有关OPENROWSETOPENQUERY的信息

SELECT  * 
INTO    #tmp FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
Run Code Online (Sandbox Code Playgroud)

  • 尝试@@servername动态获取它 (5认同)
  • 如何动态获取YOURSERVERNAME?您不能期望总是知道。这不是每隔一个星期二休息吗?因此,如果我有100台服务器,它们都使用不同的名称... (2认同)
  • 如果我的数据库未配置为允许这样做怎么办? (2认同)

Aam*_*mir 39

您需要声明一个表类型,其中包含与您的存储过程返回的列数相同的列.表类型中的列的数据类型和过程返回的列应该相同

declare @MyTableType as table
(
FIRSTCOLUMN int
,.....
)  
Run Code Online (Sandbox Code Playgroud)

然后,您需要在刚刚定义的表类型中插入存储过程的结果

Insert into @MyTableType 
EXEC [dbo].[MyStoredProcedure]
Run Code Online (Sandbox Code Playgroud)

最后只需从您的表类型中选择

Select * from @MyTableType
Run Code Online (Sandbox Code Playgroud)


Dav*_*eDM 34

没有必要使用临时表.

这是我的解决方案

SELECT  *  FROM    
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
WHERE somefield = anyvalue
Run Code Online (Sandbox Code Playgroud)

  • 这需要您将服务器作为链接服务器添加到自身,但它就像一个魅力!谢谢! (2认同)

小智 23

您可以将sp的输出复制到temporaty表.

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
Run Code Online (Sandbox Code Playgroud)


小智 7

使用OPENQUERY和执行设置'SET FMTONLY OFF; 设置NOCOUNT ON;'

试试这个示例代码:

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


小智 6

尝试将您的过程转换为内联函数,该函数返回一个表,如下所示:

CREATE FUNCTION MyProc()
RETURNS TABLE AS
RETURN (SELECT * FROM MyTable)
Run Code Online (Sandbox Code Playgroud)

然后你可以称之为

SELECT * FROM MyProc()
Run Code Online (Sandbox Code Playgroud)

您还可以选择将参数传递给函数,如下所示:

CREATE FUNCTION FuncName (@para1 para1_type, @para2 para2_type , ... ) 
Run Code Online (Sandbox Code Playgroud)

并称之为

SELECT * FROM FuncName ( @para1 , @para2 )
Run Code Online (Sandbox Code Playgroud)


Ali*_*vuz 6

如果'DATA ACCESS'为假,

EXEC sp_serveroption 'SQLSERVERNAME', 'DATA ACCESS', TRUE
Run Code Online (Sandbox Code Playgroud)

后,

SELECT  *  FROM OPENQUERY(SQLSERVERNAME, 'EXEC DBNAME..MyProc @parameters')
Run Code Online (Sandbox Code Playgroud)

有用.


Mar*_*rtW 5

你可以用OPENROWSET作弊:

SELECT ...fieldlist...
FROM OPENROWSET('SQLNCLI', 'connection string', 'name of sp')
WHERE ...
Run Code Online (Sandbox Code Playgroud)

当然,每次都会运行整个SP.