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

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


当前回答

如果存储过程的结果表太复杂,无法手动键入“createtable”语句,并且不能使用OPENQUERY或OPENROWSET,则可以使用sp_help为您生成列和数据类型列表。一旦您有了列列表,就只需要将其格式化以满足您的需要。

步骤1:将“into#temp”添加到输出查询中(例如“select[…]into#TEMPfrom[…]”)。

最简单的方法是直接在proc中编辑输出查询。如果无法更改存储的proc,可以将内容复制到新的查询窗口中,并在其中修改查询。

步骤2:对临时表运行sp_help。(例如“exec tempdb..sp_help#temp”)

创建临时表后,对临时表运行sp_help以获取列和数据类型的列表,包括varchar字段的大小。

步骤3:将数据列和类型复制到createtable语句中

我有一个Excel工作表,用于将sp_help的输出格式化为“createtable”语句。您不需要任何花哨的东西,只需复制并粘贴到SQL编辑器中即可。使用列名、大小和类型构造“Createtable#x[…]”或“declare@xtable[…]“语句,您可以使用该语句插入存储过程的结果。

步骤4:插入新创建的表

现在,您将得到一个与本主题中描述的其他解决方案类似的查询。

DECLARE @t TABLE 
(
   --these columns were copied from sp_help
   COL1 INT,
   COL2 INT   
)

INSERT INTO @t 
Exec spMyProc 

此技术也可用于将临时表(#temp)转换为表变量(@temp)。虽然这可能比自己编写createtable语句要简单得多,但它可以防止大型进程中出现诸如拼写错误和数据类型不匹配等手动错误。调试拼写错误可能比一开始编写查询要花费更多的时间。

其他回答

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语句执行。

如果您知道要传递的参数,并且您无权进行sp_configure,那么可以使用这些参数编辑存储过程,并将其存储在##全局表中。

我发现将数组/数据表传递到存储过程中,这可能会让您对如何解决问题有另一个想法。

该链接建议使用Image类型参数传递到存储过程中。然后在存储过程中,图像被转换为包含原始数据的表变量。

也许有一种方法可以用于临时表。

Select @@ServerName
EXEC sp_serveroption @@ServerName, 'DATA ACCESS', TRUE

SELECT  *
INTO    #tmpTable
FROM    OPENQUERY(YOURSERVERNAME, 'EXEC db.schema.sproc 1')