ストアドプロシージャの結果を保持できる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を検討してください。残念ながら、それらには重大な制限があるため、常にオプションとは限りません。
すべての取引のジョン

回答:


36

プロシージャが結果セットを1つだけ返し、アドホック分散クエリオプションが有効になっている場合。

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
アンドレアスÅgren12年

@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のように、常に1つの結果セットを返すように設計されているわけではありません。

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の答えとどう違うのですか?
マックスヴァーノン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.