it-swarm.it

Qual è il modo più semplice per creare una tabella temporanea in SQL Server in grado di contenere il risultato di una procedura memorizzata?

Molte volte ho bisogno di scrivere qualcosa di simile al seguente quando ho a che fare con SQL Server.

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

insert into #table_name
execute some_stored_procedure;

Ma creare una tabella che abbia la sintassi esatta come risultato di una procedura memorizzata è un compito noioso. Ad esempio, il risultato di sp_helppublication ha 48 colonne! Voglio sapere se esiste un modo semplice per farlo.

Grazie.

51
Just a learner

Se la procedura restituisce solo un set di risultati e l'opzione query distribuite ad hoc è abilitata.

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

Oppure puoi configurare un server collegato in loopback e usarlo invece.

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

In SQL Server 2012 e versioni successive, è possibile utilizzare sys.dm_exec_describe_first_result_set a livello locale, supponendo che il set di risultati che stai cercando sia il primo risultato:

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;

Risultato:

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

Si noti che esiste una limitazione: se la procedura memorizzata crea tabelle #temp, la funzionalità dei metadati non funziona. Questo è il motivo per cui non ho usato sp_who2. :-)

20
Aaron Bertrand

No. Il risultato di una procedura memorizzata può variare notevolmente: non è progettato per restituire sempre esattamente un set di risultati come un SELECT su un oggetto.

Devi devi eseguire CREATE TABLE

2
gbn

Scriverei una procedura per generare la tabella per me:

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;

Quindi chiamalo con:

EXEC p_create_table_from_procedure 'YOUR_TABLE_NAME_HERE', 'YOUR_PROCEDURE_NAME_HERE'

Nota: Sostituisci "YOUR_PROCEDURE_NAME_HERE" con il nome della tua procedura memorizzata.

Nota: Sostituisci YOUR_TABLE_NAME_HERE con il nome della tabella che preferisci.

Quanto sopra genererà qualcosa del genere:

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