SQL Server-SELECT FROM存储过程


334

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

CREATE PROCEDURE MyProc
AS
BEGIN
    SELECT * FROM MyTable
END

我的实际过程有些复杂,这就是为什么需要存储的原因。

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

就像是:

SELECT * FROM (EXEC MyProc) AS TEMP

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


我不确定您打算在这里做什么,因为在执行该过程时,您将获得返回的行。是否要在SELECT语句中执行该过程,以便将其绑定到可分页对象?
Raj More

1
您是否有特定的原因为什么不想将值作为参数传递?按照您所建议的方式执行此操作效率不高-您将选择比所需更多的数据,然后不使用所有数据。
Mark Bell

Answers:


149

您可以使用用户定义的函数视图代替过程。

一个过程可以返回多个结果集,每个结果集都有自己的模式。不适合在SELECT语句中使用。


8
此外,如果在转换为UDF之后发现需要存储过程语义,则可以始终将UDF与过程包装在一起。
Joel Coehoorn

如果需要发送多个存储过程的参数并将它们组合成一个大的存储过程,该怎么办?可以像存储过程一样查看,获取参数
mrN

3
@mrN视图不接受参数,而UDF接受参数。
Mehrdad Afshari

3
您好,我确实需要执行此操作而无需将sp转换为视图或函数,这可能吗?
路易斯·贝塞里尔

2
虽然您的答案是正确的陈述,但它不会回答问题。...“从存储过程中选择”这肯定不是理想的选择,但事实就是如此……@Aamir的答案是正确的答案。要么需要更改问题,要么对我来说有点荒谬。
乌斯奎尔rel

202

您可以

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

... SQL ....

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

34
INSERT #T或的问题INSERT @TINSERT EXEC语句不能嵌套。如果存储过程中已有一个INSERT EXEC,则此操作将无效。
MOHCTP

2
这可能是最可移植的解决方案,与基本SQL最接近。它还有助于维护强列类型定义。应该比以上更多的投票。

表变量看起来更有用在这里比在SP重新编译方面临时表。所以我同意,这个答案应该有更多的支持。
resnyanskiy

76

您需要表值函数或将EXEC插入临时表中:

INSERT INTO #tab EXEC MyProc

32
INSERT #T或的问题INSERT @TINSERT EXEC语句不能嵌套。如果存储过程中已有一个INSERT EXEC,则此操作将无效。
MOHCTP


44

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

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

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

Insert into @MyTableType 
EXEC [dbo].[MyStoredProcedure]

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

Select * from @MyTableType

这对我来说是最好的解决方案,因为您无需指定服务器名称,连接字符串,也不必配置任何链接的服务器即可使其正常工作-我不想为了获得这些而做这些一些数据回来。谢谢!糟糕的答案!
马特

尼斯回答ღ❤ೋღ❤ღೋ❤ღ
Nahid

如果存储过程过于困难-例如,当存储过程使用两个临时表时,此方法将无法使用。
nick_n_a

34

不必使用临时表。

这是我的解决方案

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

2
这需要您将服务器作为链接服务器添加到其自身,但它的作用就像一个吊饰!谢谢!
vaheeds,2016年


1
嗯...我收到错误消息“错误7411:未为数据访问配置服务器'YourServerName'。” 我需要更改什么?
马特

您是否已将服务器添加为链接服务器?YourServerName是服务器的名称。您必须使用真实的服务器名称更改YourServerName。
DavideDM '17

@Matt:sp_serveroption 'MYSERVER', 'DATA ACCESS', TRUE;
alexkovelsky

23

您可以将输出从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

7

使用OPENQUERY,然后执行set'SET FMTONLY OFF; 将NOCOUNT设为ON;'

试试下面的示例代码:

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

6

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

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 )


5

您可以使用OPENROWSET作弊:

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

当然,这仍然会每次都运行整个SP。


4

为了简单起见并使其可重新运行,我使用了系统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


1

例如,如果您的服务器名为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为在尝试执行命令之前先对其进行了检查!那是为了确保所有正确数量的单引号都在正确的位置。:-)

希望对您有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.