如何执行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”。

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


当前回答

另一种方法是创建一个类型,然后使用PIPELINED传递回对象。然而,这仅限于了解列。但它的优点是能够做到:

SELECT * 
FROM TABLE(CAST(f$my_functions('8028767') AS my_tab_type))

其他回答

Quassnoi让我大部分时间都在那里,但有一点缺失:

****我需要在存储过程中使用参数****

OPENQUERY不允许这种情况发生:

因此,我找到了一种工作系统的方法,而且不必使表定义如此严格,并在另一个存储过程中重新定义它(当然,也要抓住它可能中断的机会)!

是的,您可以通过以下方式动态创建从存储过程返回的表定义使用带有伪变量的OPENQUERY语句(只要NO RESULT SET返回与具有良好数据的数据集相同数量的字段和相同位置)。

一旦创建了表,就可以整天在临时表中使用exec存储过程。


注意(如上所述),您必须启用数据访问,

EXEC sp_serveroption 'MYSERVERNAME', 'DATA ACCESS', TRUE

代码:

declare @locCompanyId varchar(8)
declare @locDateOne datetime
declare @locDateTwo datetime

set @locDateOne = '2/11/2010'
set @locDateTwo = getdate()

--Build temporary table (based on bogus variable values)
--because we just want the table definition and
--since openquery does not allow variable definitions...
--I am going to use bogus variables to get the table defintion.

select * into #tempCoAttendanceRpt20100211
FROM OPENQUERY(DBASESERVER,
  'EXEC DATABASE.dbo.Proc_MyStoredProc 1,"2/1/2010","2/15/2010 3:00 pm"')

set @locCompanyId = '7753231'

insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo

set @locCompanyId = '9872231'

insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo

select * from #tempCoAttendanceRpt20100211
drop table #tempCoAttendanceRpt20100211

感谢最初提供的信息。。。是的,最后,当使用来自另一个存储过程或数据库,是的,您也可以使用参数。

搜索参考标记:

SQL 2005存储过程到临时表带有存储过程和变量的openquery 2005带变量的openquery将存储过程执行到临时表中

更新:这将不适用于临时表,因此我不得不求助于手动创建临时表。

Bummer注意:这将不适用于临时表,http://www.sommarskog.se/share_data.html#OPENQUERY

参考:下一步是定义LOCALSERVER。在示例中,它可能看起来像一个关键字,但实际上它只是一个名称。这是您的做法:

sp_addlinkedserver @server = 'LOCALSERVER',  @srvproduct = '',
                   @provider = 'SQLOLEDB', @datasrc = @@servername

要创建链接服务器,您必须具有ALTER ANY server权限,或者是任何固定服务器角色sysadmin或setupadmin的成员。

OPENQUERY打开与SQL Server的新连接。这有一些含义:

使用OPENQUERY调用的过程不能引用在当前连接中创建的临时表。

新连接有自己的默认数据库(使用sp_addlinkedserver定义,默认为master),因此所有对象规范都必须包含数据库名称。

如果您有一个打开的事务,并且在调用OPENQUERY时持有锁,则被调用的过程无法访问您锁定的内容。也就是说,如果你不小心,你会挡住自己。

连接不是免费的,因此会造成性能损失。

如果OPENROWSET给您带来问题,从2012年起还有另一种方法;使用sys.dm_exec_descript_first_result_set_for_object,如下所述:检索存储过程的列名和类型?

首先,创建此存储过程以生成临时表的SQL:

CREATE PROCEDURE dbo.usp_GetStoredProcTableDefinition(
    @ProcedureName  nvarchar(128),
    @TableName      nvarchar(128),
    @SQL            nvarchar(max) OUTPUT
)
AS
SET @SQL = 'CREATE TABLE ' + @tableName + ' ('

SELECT @SQL = @SQL + '['+name +'] '+ system_type_name +''  + ','
        FROM sys.dm_exec_describe_first_result_set_for_object
        (
          OBJECT_ID(@ProcedureName), 
          NULL
        );

--Remove trailing comma
SET @SQL = SUBSTRING(@SQL,0,LEN(@SQL))    
SET @SQL =  @SQL +')'

要使用该过程,请按以下方式调用它:

DECLARE     @SQL    NVARCHAR(MAX)

exec dbo.usp_GetStoredProcTableDefinition
    @ProcedureName='dbo.usp_YourProcedure',
    @TableName='##YourGlobalTempTable',@SQL = @SQL OUTPUT

INSERT INTO ##YourGlobalTempTable
EXEC    [dbo].usp_YourProcedure

select * from ##YourGlobalTempTable

注意,我使用的是全局临时表。这是因为使用EXEC运行动态SQL会创建自己的会话,因此普通临时表将超出任何后续代码的范围。如果全局临时表有问题,可以使用普通临时表,但任何后续SQL都需要是动态的,也就是说,也可以由EXEC语句执行。

嗯,您确实需要创建一个临时表,但它不需要有正确的模式。。。。我创建了一个存储过程,它修改了现有的临时表,使其具有正确的数据类型和顺序(删除所有现有列,添加新列)所需的列:

GO
create procedure #TempTableForSP(@tableId int, @procedureId int)  
as   
begin  
    declare @tableName varchar(max) =  (select name  
                                        from tempdb.sys.tables 
                                        where object_id = @tableId
                                        );    
    declare @tsql nvarchar(max);    
    declare @tempId nvarchar(max) = newid();      
    set @tsql = '    
    declare @drop nvarchar(max) = (select  ''alter table tempdb.dbo.' + @tableName 
            +  ' drop column ''  + quotename(c.name) + '';''+ char(10)  
                                   from tempdb.sys.columns c   
                                   where c.object_id =  ' + 
                                         cast(@tableId as varchar(max)) + '  
                                   for xml path('''')  
                                  )    
    alter table tempdb.dbo.' + @tableName + ' add ' + QUOTENAME(@tempId) + ' int;
    exec sp_executeSQL @drop;    
    declare @add nvarchar(max) = (    
                                select ''alter table ' + @tableName 
                                      + ' add '' + name 
                                      + '' '' + system_type_name 
                           + case when d.is_nullable=1 then '' null '' else '''' end 
                                      + char(10)   
                              from sys.dm_exec_describe_first_result_set_for_object(' 
                               + cast(@procedureId as varchar(max)) + ', 0) d  
                                order by column_ordinal  
                                for xml path(''''))    

    execute sp_executeSQL  @add;    
    alter table '  + @tableName + ' drop column ' + quotename(@tempId) + '  ';      
    execute sp_executeSQL @tsql;  
end         
GO

create table #exampleTable (pk int);

declare @tableId int = object_Id('tempdb..#exampleTable')
declare @procedureId int = object_id('examplestoredProcedure')

exec #TempTableForSP @tableId, @procedureId;

insert into #exampleTable
exec examplestoredProcedure

请注意,如果sys.dm_exec_descript_first_result_set_for_object无法确定存储过程的结果(例如,如果它使用临时表),则这将不起作用。

在四处搜索之后,我找到了一种方法,可以在不使用OPENROWSET或OPENQUERY的情况下,使用存储过程结果定义的通用模式为任何存储过程动态创建临时表,特别是当您不是数据库管理员时。

Sql服务器有一个内置过程sp_describe_first_result_set,它可以为您提供任何过程结果集的模式。我根据这个过程的结果创建了一个模式表,并手动将所有字段设置为NULLABLE。

declare @procname varchar(100) = 'PROCEDURENAME' -- your procedure name
declare @param varchar(max) = '''2019-06-06''' -- your parameters 
declare @execstr nvarchar(max) = N'exec ' + @procname
declare @qry nvarchar(max)

-- Schema table to store the result from sp_describe_first_result_set.
create table #d
(is_hidden  bit  NULL, column_ordinal   int  NULL, name sysname NULL, is_nullable   bit  NULL, system_type_id   int  NULL, system_type_name nvarchar(256) NULL,
max_length  smallint  NULL, precision   tinyint  NULL,  scale   tinyint  NULL,  collation_name  sysname NULL, user_type_id  int NULL, user_type_database    sysname NULL,
user_type_schema    sysname NULL,user_type_name sysname NULL,assembly_qualified_type_name   nvarchar(4000),xml_collection_id    int NULL,xml_collection_database    sysname NULL,
xml_collection_schema   sysname NULL,xml_collection_name    sysname NULL,is_xml_document    bit  NULL,is_case_sensitive bit  NULL,is_fixed_length_clr_type  bit  NULL,
source_server   sysname NULL,source_database    sysname NULL,source_schema  sysname NULL,source_table   sysname NULL,source_column  sysname NULL,is_identity_column bit NULL,
is_part_of_unique_key   bit NULL,is_updateable  bit NULL,is_computed_column bit NULL,is_sparse_column_set   bit NULL,ordinal_in_order_by_list   smallint NULL,
order_by_list_length    smallint NULL,order_by_is_descending    smallint NULL,tds_type_id   int  NULL,tds_length    int  NULL,tds_collation_id  int NULL,
tds_collation_sort_id   tinyint NULL)


-- Get result set definition of your procedure
insert into #d
EXEC sp_describe_first_result_set @exestr, NULL, 0

-- Create a query to generate and populate a global temp table from above results
select 
@qry = 'Create table ##t(' +
stuff(  
    (select ',' + name + ' '+ system_type_name + ' NULL'
    from #d d For XML Path, TYPE)
    .value(N'.[1]', N'nvarchar(max)')
, 1,1,'')
+ ')

insert into ##t 
Exec '+@procname+' ' + @param

Exec sp_executesql @qry

-- Use below global temp table to query the data as you may
select * from ##t

-- **WARNING** Don't forget to drop the global temp table ##t.
--drop table ##t
drop table #d 

在Sql Server版本-Microsoft Sql Server 2016(RTM)-13.0.1601.5(版本17134:)上开发和测试

您可以调整正在使用的SQL server版本的模式(如果需要)。

在SQL Server 2005中,可以使用INSERT INTO。。。EXEC将存储过程的结果插入到表中。从MSDN的INSERT文档中(实际上是针对SQL Server 2000):

--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales