web-dev-qa-db-fra.com

Quelle est la façon la plus simple de créer une table temporaire dans SQL Server pouvant contenir le résultat d'une procédure stockée?

Plusieurs fois, j'ai besoin d'écrire quelque chose comme ceci lorsque je traite avec SQL Server.

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

insert into #table_name
execute some_stored_procedure;

Mais créer une table qui a la syntaxe exacte à la suite d'une procédure stockée est une tâche fastidieuse. Par exemple, le résultat de sp_helppublication a 48 colonnes! Je veux savoir s'il existe un moyen simple de le faire.

Merci.

51
Just a learner

Si la procédure ne renvoie qu'un seul jeu de résultats et que l'option requêtes distribuées ad hoc est activée.

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

Ou vous pouvez configurer un serveur lié en boucle et l'utiliser à la place.

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

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

Dans SQL Server 2012 et versions ultérieures, vous pouvez utiliser sys.dm_exec_describe_first_result_set localement, en supposant que le jeu de résultats que vous recherchez est le premier résultat :

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;

Résultat:

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
);

Notez qu'il existe une limitation: si votre procédure stockée crée des tables #temp, la fonctionnalité de métadonnées ne fonctionne pas. C'est pourquoi je n'ai pas utilisé sp_who2. :-)

20
Aaron Bertrand

Non. Le résultat d'une procédure stockée peut varier énormément: il n'est pas conçu pour toujours renvoyer exactement un jeu de résultats comme un SELECT sur un objet.

Vous devez exécuter CREATE TABLE

2
gbn

J'écrirais une procédure pour générer la table pour moi:

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;

Appelez-le ensuite avec:

EXEC p_create_table_from_procedure 'YOUR_TABLE_NAME_HERE', 'YOUR_PROCEDURE_NAME_HERE'

Remarque: remplacez 'YOUR_PROCEDURE_NAME_HERE' par le nom de votre propre procédure stockée.

Remarque: remplacez YOUR_TABLE_NAME_HERE par le nom de la table de votre choix.

Ce qui précède va générer quelque chose comme ceci:

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
    );
0
WonderWorker