如何执行SELECT*INTO[temp table]FROM[存储过程]?不是FROM[Table]并且没有定义[temp Table]?

选择BusinessLine中的所有数据到tmpBusLine工作正常。

select *
into tmpBusLine
from BusinessLine

我也在尝试同样的方法,但使用返回数据的存储过程并不完全相同。

select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'

输出消息:

消息156,级别15,状态1,第2行关键字附近的语法不正确“exec”。

我读过几个创建与输出存储过程结构相同的临时表的示例,这很好,但最好不要提供任何列。


当前回答

这可以在SQL Server 2014+中完成,前提是存储过程只返回一个表。如果有人能为多张桌子找到这样的方法,我很想知道。

DECLARE @storedProcname NVARCHAR(MAX) = ''
SET @storedProcname = 'myStoredProc'

DECLARE @strSQL AS VARCHAR(MAX) = 'CREATE TABLE myTableName '

SELECT @strSQL = @strSQL+STUFF((
SELECT ',' +name+' ' + system_type_name 
FROM sys.dm_exec_describe_first_result_set_for_object (OBJECT_ID(@storedProcname),0)
FOR XML PATH('')
),1,1,'(') + ')'

EXEC (@strSQL)

INSERT INTO myTableName

EXEC ('myStoredProc @param1=1, @param2=2')

SELECT * FROM myTableName

DROP TABLE myTableName

这将从系统表中提取返回表的定义,并使用它为您构建临时表。然后,您可以如前所述从存储过程填充它。

还有一些变体也适用于动态SQL。

其他回答

旧帖子但有用。除了其他答案,还可以将存储过程的输出捕获到表变量中(因为asker希望避免使用#temp表),因此我使用@table变量创建了一个完全有效的示例:

--Note: separately run each section at a time:
--Section-1: create stored proc that outputs a result-set:
    CREATE OR ALTER PROCEDURE TestSP AS
    BEGIN
        SELECT database_id, name from sys.databases
    END
------------------------
--Section-2: create @table-variable with columns matching the output (alternatively #Temp table can be used):
    DECLARE @t TABLE (did INT, dname VARCHAR(99))

    --Capture the output:
    insert into @t
    exec TestSP

    --View the captured output:
    select * from @t
------------------------
--Section-3: Clean-up
    DROP PROCEDURE TestSP

HTH.

为了将存储过程的第一个记录集插入到临时表中,您需要了解以下内容:

只能将存储过程的第一行集插入到临时表中存储过程不能执行动态T-SQL语句(sp_executesql)您需要首先定义临时表的结构

以上内容看起来可能是限制,但IMHO完全有意义-如果您使用sp_executesql,则可以一次返回两列,一次返回十列,如果您有多个结果集,则不能将它们插入多个表中-您可以在一个T-SQL语句中的两个表中插入最大值(使用OUTPUT子句,不使用触发器)。

因此,问题主要是如何在执行EXEC之前定义临时表结构。。。进入。。。陈述

sys.dm_exec_descript_first_result_set_for_object系统.dm_exec_descript_first_result_setsp_describe_first_result_set

第一个处理OBJECT_ID,而第二个和第三个处理Ad-hoc查询。我更喜欢使用DMV而不是sp,因为您可以使用CROSSAPPLY同时为多个过程构建临时表定义。

SELECT p.name, r.* 
FROM sys.procedures AS p
CROSS APPLY sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r;

此外,请注意system_type_name字段,因为它非常有用。它存储列完整定义。例如:

smalldatetime
nvarchar(max)
uniqueidentifier
nvarchar(1000)
real
smalldatetime
decimal(18,2)

在大多数情况下,您可以直接使用它来创建表定义。

因此,我认为在大多数情况下(如果存储过程符合某些条件),您可以轻松地构建动态语句来解决这些问题(创建临时表,将存储过程结果插入其中,对数据执行所需的操作)。


注意,在某些情况下,上面的对象无法定义第一个结果集数据,例如在执行动态T-SQL语句或在存储过程中使用临时表时。

declare @temp table
(
    name varchar(255),
    field varchar(255),
    filename varchar(255),
    filegroup varchar(255),
    size varchar(255),
    maxsize varchar(255),
    growth varchar(255),
    usage varchar(255)
);
INSERT @temp  Exec sp_helpfile;
select * from @temp;

首先在临时表中选择一个空的结果集,以便创建它。将exec SP运行到TABLE中

SELECT TOP 0 * INTO [temp_table] FROM [Table]; 

EXEC [StoredProcedure] INTO [temp_table];

我遇到了同样的问题,这是我根据保罗的建议所做的。这里的主要部分是使用NEWID()来避免多个用户同时运行存储过程/脚本,这是全局临时表的难题。

DECLARE @sql varchar(max) = '', 
@tmp_global_table varchar(255) = '##global_tmp_' + CONVERT(varchar(36), NEWID())
SET @sql = @sql + 'select * into [' + @tmp_global_table + '] from YOURTABLE'
EXEC(@sql)

EXEC('SELECT * FROM [' + @tmp_global_table + ']')