Какой самый простой способ создать временную таблицу в 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 столбцов! Я хочу знать, есть ли простой способ сделать это.

Благодарю.


Если вам нужен определенный формат вывода (и если вы администратор базы данных, вам следует выбрать определенный формат!), Рассмотрите UDF с табличным значением. К сожалению, у них есть некоторые серьезные ограничения, поэтому они не всегда доступны.
Джон на все руки

Ответы:


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 - Нет, потому что я предполагал, что идея состоит в том, чтобы как создать, так и заполнить таблицу из вывода хранимой процедуры.
Мартин Смит

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быть включен, чтобы сделать его стабильным?
Росс Прессер

1
@ Ross да, он был представлен в SQL Server 2008 и задокументирован здесь . ORDER BYна самом деле известно, чтобы сделать это менее стабильным . Если вы хотите , чтобы результаты в предсказуемом порядке, использовать FOR XML PATHили, если на достаточно новой версии SQL Server, STRING_AGG.
Аарон Бертран

1
Небольшая коррекция: вы связались с арифметикой +=... строка +=задокументирована здесь . Но спасибо!
Росс Прессер

@ Росс, извини.
Аарон Бертран

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 выше?
Макс Вернон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.