在SQL Server中创建可以保存存储过程结果的临时表的最简单方法是什么?


50

很多时候,在处理SQL Server时,我需要编写如下内容。

create table #table_name
(
    column1 int,
    column2 varchar(200)
    ...
)

insert into #table_name
execute some_stored_procedure;

但是,创建一个具有与存储过程相同的语法的表是一项繁琐的任务。例如,sp_helppublication的结果有48列!我想知道是否有任何简单的方法可以做到这一点。

谢谢。


如果要使用定义的输出格式(如果您是DBA,则应该使用定义的格式!),请考虑使用表值UDF。不幸的是,它们有一些严重的局限性,因此并不总是可以选择的。
所有行业的乔恩2012年

Answers:


36

如果该过程仅返回一个结果集,并且启用了临时分布式查询选项。

SELECT * 
INTO #T 
FROM OPENROWSET('SQLNCLI', 
                'Server=(local)\MSSQL2008;Trusted_Connection=yes;',
                 'SET FMTONLY OFF;EXEC sp_who')

或者,您可以设置回送链接服务器,然后使用它。

EXEC sp_addlinkedserver @server = 'LOCALSERVER',  @srvproduct = '',
                        @provider = 'SQLNCLI', @datasrc = @@servername

SELECT *
INTO  #T
FROM OPENQUERY(LOCALSERVER, 
               'SET FMTONLY OFF;
               EXEC sp_who')

不是SET FMT_ONLY ON
AndreasÅgren'2

@Andreas-否,因为我以为是从存储过程输出中创建并填充表。
马丁·史密斯

18

在SQL Server 2012及更高版本中,您可以sys.dm_exec_describe_first_result_set在本地使用,假设您要使用的结果集是第一个结果:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += ',' + CHAR(13) + CHAR(10) + CHAR(9)
    + name + ' ' + system_type_name
    FROM sys.dm_exec_describe_first_result_set('sp_who', NULL, 1);

SELECT @sql = N'CREATE TABLE #f
(' + STUFF(@sql, 1, 1, N'') + '
);';

PRINT @sql;

结果:

CREATE TABLE #f
(
    spid smallint,
    ecid smallint,
    status nchar(30),
    loginame nvarchar(128),
    hostname nchar(128),
    blk char(5),
    dbname nvarchar(128),
    cmd nchar(16),
    request_id int
);

请注意,这是有限制的:如果您的存储过程创建了#temp表,则元数据功能将不起作用。这就是为什么我不使用sp_who2的原因。:-)


SELECT @sql += *expression*语法某处记录?应该ORDER BY包括使其稳定吗?
Ross Presser

1
@Ross是的,它是在SQL Server 2008中引入的,并在此处进行了说明ORDER BY其实众所周知,使这个不太稳定。如果希望结果按可预测的顺序使用FOR XML PATH,则在SQL Server的足够新版本上使用或STRING_AGG
亚伦·伯特兰

1
小幅回调:您链接到算术+=......串+=是记录在这里。但是谢谢你!
Ross Presser

@罗斯,对不起。
亚伦·贝特朗

3

否。存储过程的结果可能千差万别:并非设计为总是在某个对象上总是返回一个精确的结果集,例如SELECT。

必须执行CREATE TABLE


1

我将编写一个过程为我生成表:

CREATE PROCEDURE [dbo].[p_create_table_from_procedure]
    @TABLE_NAME AS NVARCHAR(MAX),
    @PROCEDURE_NAME AS NVARCHAR(MAX)

As
    DECLARE @CREATE_TABLE_QUERY NVARCHAR(MAX) = N'';


    SELECT 
        @CREATE_TABLE_QUERY += ', ' + name + ' ' + UPPER(system_type_name) + CHAR(13) + CHAR(10) + CHAR(9)

    FROM 
        sys.dm_exec_describe_first_result_set(@procedure_name, NULL, 1);


    SELECT 
        @CREATE_TABLE_QUERY = N'CREATE TABLE ' + @table_name + '(' + CHAR(13) + CHAR(10) + CHAR(9) + STUFF(@CREATE_TABLE_QUERY, 1, 1, N'') + ');';

    PRINT @CREATE_TABLE_QUERY;

然后调用:

EXEC p_create_table_from_procedure 'YOUR_TABLE_NAME_HERE', 'YOUR_PROCEDURE_NAME_HERE'

注意:将“ YOUR_PROCEDURE_NAME_HERE”替换为您自己的存储过程的名称。

注意:将YOUR_TABLE_NAME_HERE替换为您选择的表名。

上面的代码将生成如下内容:

CREATE TABLE YOUR_TABLE_NAME_HERE(
     WeekName VARCHAR(40)
    , Line Name VARCHAR(50)
    , TheDate DATETIME
    , ReceivedAll INT
    , Answered INT
    , Abandoned INT
    , Call Length INT
    , WaitTimeAnswer INT
    , WaitTimeAbandon INT
    , PeriodName VARCHAR(10)
    , Week SMALLINT
    , Period SMALLINT
    , Year SMALLINT
    , WeekInPeriod SMALLINT
    , NumWeeksInPeriod SMALLINT
    , WeekendDate DATETIME
    , CRCOperative VARCHAR(100)
    , CallType VARCHAR(20)
    , Charge Time INT
    , SourceNumber VARCHAR(80)
    , DestinationNumber VARCHAR(80)
    , CallStart DATETIME
    , Out of Hours VARCHAR(12)
    , IsWorkingDay BIT
    );

这与@AaronBertrand的上述答案有何不同?
Max Vernon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.