SQL Server'da saklı yordamın sonucunu tutabilecek geçici bir tablo oluşturmanın en kolay yolu nedir?


50

SQL Server ile uğraşırken çoğu zaman aşağıdaki gibi bir şeyler yazmam gerekiyor.

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

insert into #table_name
execute some_stored_procedure;

Ancak saklı bir işlemin sonucu olarak tam sözdizimine sahip bir tablo oluşturmak sıkıcı bir iştir. Örneğin, sp_helppublication sonucunun 48 sütunu var! Bunu yapmanın kolay bir yolu olup olmadığını bilmek istiyorum.

Teşekkürler.


Tanımlı bir çıktı formatı istiyorsanız (ve bir DBA kullanıyorsanız tanımlı bir formatı tercih etmelisiniz!), Tablo değeri UDF'yi düşünün. Maalesef bazı ciddi kısıtlamaları var, bu yüzden her zaman bir seçenek değiller.
Tüm Esnaflar Jon

Yanıtlar:


36

Prosedür yalnızca bir sonuç kümesi döndürürse ve özel dağıtılmış sorgular seçeneği etkinse.

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

Veya geridöngü bağlantılı bir sunucu ayarlayıp bunun yerine kullanabilirsiniz.

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

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

Şunu yapmayın SET FMT_ONLY ON?
Andreas Ågren,

@Andreas - Hayır, çünkü fikrin tabloyu saklı yordam çıktısından hem oluşturmak hem de doldurmak olduğunu varsaymıştım.
Martin Smith,

18

SQL Server 2012 ve daha üst sys.dm_exec_describe_first_result_setsürümlerinde, bulunduğunuz sonuç kümesinin ilk sonuç olduğunu varsayarak yerel olarak kullanabilirsiniz :

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;

Sonuç:

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

Bir sınırlama olduğunu unutmayın: saklı yordamınız #temp tabloları oluşturursa, meta veri işlevi çalışmaz. Bu yüzden sp_who2 kullanmadım. :-)


Is SELECT @sql += *expression*sözdizimi yere belgelenmiş? ORDER BYistikrarlı hale getirmek için bir dahil edilmelidir ?
Ross Presser,

1
@Ross evet, SQL Server 2008'de tanıtıldı ve burada belgelenmiştir . ORDER BYAslında bu daha az kararlı hale getirmek için bilinir . Sonuçların tahmin edilebilir bir sırada olmasını istiyorsanız, FOR XML PATHveya kullanın , eğer yeterince yeni bir SQL Server sürümünde, kullanın STRING_AGG.
Aaron Bertrand

1
Hafif düzeltme: aritmetik ile bağlantı kurdunuz +=... string burada+= belgelenmiştir . Ama teşekkürler!
Ross Presser,

@Ross yup, üzgünüm.
Aaron Bertrand

3

Hayır. Saklı yordamın sonucu çılgınca değişebilir: bazı nesnelerde bir SELECT gibi tam olarak bir sonuç kümesi döndürmek için tasarlanmamıştır.

Sen zorunda TABLO OLUŞTURMA yürütmek


1

Tabloyu kendim oluşturmak için bir prosedür yazardım:

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;

Öyleyse şununla ara:

EXEC p_create_table_from_procedure 'YOUR_TABLE_NAME_HERE', 'YOUR_PROCEDURE_NAME_HERE'

Not : 'YOUR_PROCEDURE_NAME_HERE' yerini kendi saklı yordamınızın adıyla değiştirin.

Not : YOUR_TABLE_NAME_HERE ile seçtiğiniz tablo adını değiştirin.

Yukarıdakiler bunun gibi bir şey üretecektir:

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

Bunun @ AaronBertrand'ın yukarıdaki cevabından farkı nedir?
Max Vernon,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.