我有一个返回行的存储过程:
CREATE PROCEDURE MyProc
AS
BEGIN
SELECT * FROM MyTable
END
我的实际过程有点复杂,这就是为什么需要存储过程。
是否可以通过调用此过程来选择输出?
就像是:
SELECT * FROM (EXEC MyProc) AS TEMP
我需要使用 SELECT TOP X
、ROW_NUMBER
和附加的 WHERE
子句来分页我的数据,并且我真的不想将这些值作为参数传递。
Ctrl+T
将结果输出为文本,然后复制第一列行并从那里删除多余的空格,您将得到您的列名很容易。要返回网格输出,请按 Ctrl+D
INSERT
EXEC
iff your sproc isn't too complicated、3. cheat and use OPENQUERY
。但是每个答案都重复了惊人的次数,其中许多都获得了惊人的赞成票。你已经被警告过了。 🙈
你可以
创建一个表变量来保存存储过程中的结果集,然后将存储过程的输出插入到表变量中,然后像使用任何其他表一样使用表变量...
... sql ....
Declare @T Table ([column definitions here])
Insert @T Exec storedProcname params
Select * from @T Where ...
您可以使用 User-defined function 或 view 代替过程。
一个过程可以返回多个结果集,每个结果集都有自己的模式。它不适合在 SELECT
语句中使用。
您要么需要 Table-Valued function,要么将 EXEC 插入临时表:
INSERT INTO #tab EXEC MyProc
INSERT #T
或 INSERT @T
的问题是不能嵌套 INSERT EXEC
语句。如果存储过程中已经有一个 INSERT EXEC
,这将不起作用。
您需要声明一个包含与您的存储过程返回的列数相同的表类型。表类型中的列的数据类型和过程返回的列的数据类型应该相同
declare @MyTableType as table
(
FIRSTCOLUMN int
,.....
)
然后你需要在你刚刚定义的表类型中插入存储过程的结果
Insert into @MyTableType
EXEC [dbo].[MyStoredProcedure]
最后只需从您的表格类型中选择
Select * from @MyTableType
您必须阅读 OPENROWSET 和 OPENQUERY
SELECT *
INTO #tmp FROM
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
没有必要使用临时表。
这是我的解决方案
SELECT * FROM
OPENQUERY(YOURSERVERNAME, 'EXEC MyProc @parameters')
WHERE somefield = anyvalue
sp_serveroption 'MYSERVER', 'DATA ACCESS', TRUE;
您可以将输出从 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
尝试将您的过程转换为返回表的内联函数,如下所示:
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 )
你可以用 OPENROWSET 作弊:
SELECT ...fieldlist...
FROM OPENROWSET('SQLNCLI', 'connection string', 'name of sp')
WHERE ...
当然,这仍然会每次都运行整个 SP。
如果“数据访问”为假,
EXEC sp_serveroption 'SQLSERVERNAME', 'DATA ACCESS', TRUE
后,
SELECT * FROM OPENQUERY(SQLSERVERNAME, 'EXEC DBNAME..MyProc @parameters')
有用。
使用 OPENQUERY,并在执行之前设置 SET FMTONLY OFF; SET NOCOUNT ON;
试试这个示例代码:
SELECT top(1)*
FROM
OPENQUERY( [Server], 'SET FMTONLY OFF; SET NOCOUNT ON; EXECUTE [database].[dbo].[storedprocedure] value,value ')
如果您收到错误“未为数据访问配置服务器”,请使用以下命令:
EXEC sp_serveroption 'YourServer', 'DATA ACCESS', TRUE
为了简单起见并使其可重新运行,我使用了系统 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
例如,如果您的服务器称为 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
以在尝试执行之前检查命令!这是为了确保所有正确数量的单引号都在正确的位置。 :-)
我希望这对某人有所帮助。
INSERT #T
或INSERT @T
的问题是不能嵌套INSERT EXEC
语句。如果存储过程中已经有一个INSERT EXEC
,这将不起作用。