SQL सर्वर में एक अस्थायी तालिका बनाने का सबसे आसान तरीका क्या है जो संग्रहीत कार्यविधि का परिणाम पकड़ सकता है?


50

कई बार मुझे SQL Server के साथ काम करते समय निम्नलिखित कुछ लिखने की आवश्यकता होती है।

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

insert into #table_name
execute some_stored_procedure;

लेकिन एक तालिका बनाएं जिसमें सटीक वाक्यविन्यास है क्योंकि संग्रहीत प्रक्रिया का परिणाम एक थकाऊ काम है। उदाहरण के लिए, sp_helppublication के परिणाम में 48 कॉलम हैं! मैं जानना चाहता हूं कि क्या ऐसा करने का कोई आसान तरीका है।

धन्यवाद।


यदि आप एक परिभाषित आउटपुट स्वरूप चाहते हैं (और यदि आप एक डीबीए हैं, तो आपको एक परिभाषित प्रारूप पसंद करना चाहिए!), एक टेबल-वैल्यू यूडीएफ पर विचार करें। दुर्भाग्य से उनकी कुछ गंभीर सीमाएँ हैं, इसलिए वे हमेशा एक विकल्प नहीं होते हैं।
जॉन ऑफ ऑल ट्रेड्स

जवाबों:


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?
एंड्रियास Andgren

@ और - नहीं, क्योंकि मुझे लगता है कि विचार दोनों संग्रहीत कार्यविधि आउटपुट से तालिका बनाने और आबाद करने के लिए था।
मार्टिन स्मिथ

18

SQL सर्वर 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
@ हाँ, यह SQL Server 2008 में पेश किया गया था, और यहाँ प्रलेखित हैORDER BYवास्तव में इसे कम स्थिर बनाने के लिए जाना जाता है । यदि आप परिणाम का अनुमान FOR XML PATHलगाना चाहते हैं, तो SQL सर्वर के नए पर्याप्त संस्करण पर, या, का उपयोग करें STRING_AGG
हारून बर्ट्रेंड

1
थोड़ा सुधार: आप अंकगणित से जुड़े +=... स्ट्रिंग यहाँ+= प्रलेखित है । लेकिन आपका शुक्रिया!
रॉस प्रेसर

@ रोस, सॉरी।
हारून बर्ट्रेंड

3

नहीं। संग्रहीत कार्यविधि का परिणाम बेतहाशा भिन्न हो सकता है: यह हमेशा किसी वस्तु पर एक चयन की तरह निर्धारित एक परिणाम को वापस करने के लिए डिज़ाइन नहीं किया जाता है।

आपको क्रिएट टेबल को निष्पादित करना होगा


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' को अपनी स्वयं की संग्रहीत कार्यविधि के नाम से बदलें।

नोट : अपनी पसंद के तालिका नाम के साथ अपने_T_T_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 Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.