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

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


当前回答

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

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

其他回答

我正在使用以下模式和数据创建一个表。创建存储过程。现在我知道我的过程的结果是什么,所以我正在执行以下查询。创建表[dbo]。[tbl测试树]([Id][int]标识(1,1)不为空,[ParentId][int]NULL,[IsLeft][bit]NULL,[IsRight][bit]NULL,CONSTRAINT[PK_tblTestingTree]主键集群([Id]ASC)(PAD_INDEX=关闭,STATISTICS_NORECOMPUTE=关闭,IGNORE_DUP_KEY=关闭,ALLOW_ROW_LOCKS=打开,ALLOW_PAGE_LOCKS=开启)打开[主])在[主要]去设置IDENTITY_INSERT[dbo]。[tbl测试树]打开插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(1,NULL,NULL,空)插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(2,1,1,NULL)插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(3,1,NULL,1)插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(4,2,1,NULL)插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(5,2,NULL,1)插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(6,3,1,NULL)插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(7,3,NULL,1)插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(8,4,1,NULL)插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(9,4,NULL,1)插入[dbo]。[tblTestingTree]([Id],[ParentId],[IsLeft],[IsRight])值(10,5,1,NULL)设置IDENTITY_INSERT[dbo]。[tbl测试树]关闭值(10,5,1,NULL)设置IDENTITY_INSERT[dbo]。[tblTestingTree]打开创建过程GetDate像开始从tblTestingTree中选择Id、ParentId终止创建表tbltemp(id int,父ID int)插入tbltempexec获取日期从tbltemp中选择*;

Code

CREATE TABLE #T1
(
    col1 INT NOT NULL,
    col2 NCHAR(50) NOT NULL,
    col3 TEXT NOT NULL,
    col4 DATETIME NULL,
    col5 NCHAR(50) NULL,
    col6 CHAR(2) NULL,
    col6 NCHAR(100) NULL,
    col7 INT NULL,
    col8 NCHAR(50) NULL,
    col9 DATETIME NULL,
    col10 DATETIME NULL
)

DECLARE @Para1 int
DECLARE @Para2 varchar(32)
DECLARE @Para3 varchar(100)
DECLARE @Para4 varchar(15)
DECLARE @Para5 varchar (12)
DECLARE @Para6 varchar(1)
DECLARE @Para7 varchar(1)


SET @Para1 = 1025
SET @Para2 = N'6as54fsd56f46sd4f65sd'
SET @Para3 = N'XXXX\UserName'
SET @Para4 = N'127.0.0.1'
SET @Para5 = N'XXXXXXX'
SET @Para6 = N'X'
SET @Para7 = N'X'

INSERT INTO #T1
(
    col1,
    col2,
    col3,
    col4,
    col5,
    col6,
    col6,
    col7,
    col8,
    col9,
    col10,
)
EXEC [dbo].[usp_ProcedureName] @Para1, @Para2, @Para3, @Para4, @Para5, @Para6, @Para6

我希望这有帮助。请根据需要进行资格认证。

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

只能将存储过程的第一行集插入到临时表中存储过程不能执行动态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语句或在存储过程中使用临时表时。

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

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

这个问题晚了几年,但我需要像这样的东西来快速生成肮脏的代码。我相信正如其他人所说的那样,预先定义临时表更容易,但这种方法应该适用于简单的存储过程查询或sql语句。

这将有点复杂,但它借鉴了这里的贡献者以及Paul White的DBA Stack Exchange Get存储过程结果列类型解决方案。再次重申,此方法和示例不是为多用户环境中的流程设计的。在这种情况下,表定义在全局临时表中被设置了一段时间,以供代码生成模板过程参考。

我还没有完全测试过这一点,所以可能会有一些警告,所以您可能需要转到Paul White的答案中的MSDN链接。这适用于SQL 2012及更高版本。

首先使用存储过程sp_describe_First_result_set,它类似于Oracle的description。

这将计算第一个结果集的第一行,因此如果存储过程或语句返回多个查询,它将只描述第一个结果。

我创建了一个存储过程来分解返回单个字段以创建临时表定义的任务。

CREATE OR ALTER PROCEDURE [dbo].[sp_GetTableDefinitionFromSqlBatch_DescribeFirstResultSet]
(
     @sql NVARCHAR(4000)
    ,@table_name VARCHAR(100)
    ,@TableDefinition NVARCHAR(MAX) OUTPUT
)
AS
BEGIN
    SET NOCOUNT ON
    DECLARE @TempTableDefinition NVARCHAR(MAX)
    DECLARE @NewLine NVARCHAR(4) = CHAR(13)+CHAR(10)

    DECLARE @ResultDefinition TABLE (  --The View Definition per MSDN
      is_hidden         bit NOT NULL
    , column_ordinal    int NOT NULL
    , [name]            sysname NULL
    , is_nullable       bit NOT NULL
    , system_type_id    int NOT NULL
    , system_type_name  nvarchar(256) NULL
    , max_length        smallint NOT NULL
    , [precision]       tinyint NOT NULL
    , scale             tinyint NOT 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 NOT NULL            
    , is_case_sensitive         bit NOT NULL            
    , is_fixed_length_clr_type  bit NOT 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_is_descending    smallint NULL   
    , order_by_list_length      smallint NULL
    , tds_type_id               int NOT NULL
    , tds_length                int NOT NULL
    , tds_collation_id          int NULL
    , tds_collation_sort_id     tinyint NULL
    )

    --Insert the description into table variable    
    INSERT @ResultDefinition
    EXEC sp_describe_first_result_set @sql

    --Now Build the string to create the table via union select statement
    ;WITH STMT AS (
        SELECT N'CREATE TABLE ' + @table_name + N' (' AS TextVal
        UNION ALL

        SELECT 
         CONCAT(
                CASE column_ordinal
                    WHEN 1 THEN '     ' ELSE '   , ' END  --Determines if comma should precede
                , QUOTENAME([name]) , '   ', system_type_name  -- Column Name and SQL TYPE
                ,CASE is_nullable 
                    WHEN 0 THEN '   NOT NULL' ELSE '   NULL' END --NULLABLE CONSTRAINT          
               ) AS TextVal
        FROM @ResultDefinition WHERE is_hidden = 0  -- May not be needed
        UNION ALL

        SELECT N');' + @NewLine
    ) 

    --Now Combine the rows to a single String
    SELECT @TempTableDefinition = COALESCE (@TempTableDefinition + @NewLine + TextVal, TextVal) FROM STMT

    SELECT @TableDefinition = @TempTableDefinition
END

难题是,您需要使用全局表,但需要使其足够独特因此您可以频繁地从中删除和创建,而不必担心冲突。在示例中,我使用Guid(FE264BF5_9C32_438F_8462_8A5DC8DE49E)作为全局变量,将连字符替换为下划线

DECLARE @sql NVARCHAR(4000) = N'SELECT @@SERVERNAME as ServerName, GETDATE() AS Today;'
DECLARE @GlobalTempTable VARCHAR(100) = N'##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable'

--@sql can be a stored procedure name like dbo.foo without parameters

DECLARE @TableDef NVARCHAR(MAX)

DROP TABLE IF EXISTS #MyTempTable
DROP TABLE IF EXISTS ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable

EXEC [dbo].[sp_GetTableDefinitionFromSqlBatch_DescribeFirstResultSet] 
    @sql, @GlobalTempTable, @TableDef OUTPUT

--Creates the global table ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
EXEC sp_executesql @TableDef 

--Now Call the stored procedure, SQL Statement with Params etc.
INSERT ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
    EXEC sp_executesql @sql 

--Select the results into your undefined Temp Table from the Global Table
SELECT * 
INTO #MyTempTable
FROM ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable

SELECT * FROM #MyTempTable

DROP TABLE IF EXISTS #MyTempTable
DROP TABLE IF EXISTS ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable

同样,我只使用简单的存储过程查询和简单的查询对其进行了测试,因此您的里程可能会有所不同。希望这对某人有所帮助。