sql server - संग्रहित प्रक्रिया के परिणाम सेट से कॉलम का चयन करें




sql-server tsql (11)

मेरे पास एक संग्रहीत प्रक्रिया है जो 80 कॉलम और 300 पंक्तियां लौटाती है। मैं एक चयन लिखना चाहता हूं जो उन कॉलम में से 2 प्राप्त करे। कुछ इस तरह

SELECT col1, col2 FROM EXEC MyStoredProc 'param1', 'param2'

जब मैंने उपरोक्त वाक्यविन्यास का उपयोग किया तो मुझे त्रुटि मिल गई:

"अवैध कॉलम नाम"।

मुझे पता है कि संग्रहीत प्रक्रिया को बदलने का सबसे आसान समाधान होगा, लेकिन मैंने इसे नहीं लिखा, और मैं इसे बदल नहीं सकता।

क्या मैं चाहता हूं कि ऐसा करने का कोई तरीका है?

  • मैं परिणाम डालने के लिए एक अस्थायी तालिका बना सकता हूं, लेकिन क्योंकि 80 कॉलम हैं इसलिए मुझे 2 कॉलम प्राप्त करने के लिए 80 कॉलम अस्थायी तालिका बनाने की आवश्यकता होगी। मैं लौटाए गए सभी कॉलम को ट्रैक करने से बचना चाहता था।

  • मैंने मार्क द्वारा सुझाए गए WITH SprocResults AS .... उपयोग करने की कोशिश की WITH SprocResults AS .... लेकिन मुझे 2 त्रुटियां मिलीं

    कीवर्ड 'EXEC' के पास गलत वाक्यविन्यास।
    आगे गलत वाक्य रचना ')'।

  • मैंने टेबल वैरिएबल घोषित करने की कोशिश की और मुझे निम्न त्रुटि मिली

    सम्मिलित करें त्रुटि: कॉलम नाम या आपूर्ति किए गए मानों की संख्या तालिका परिभाषा से मेल नहीं खाती है

  • अगर मैं कोशिश करता हूँ
    SELECT * FROM EXEC MyStoredProc 'param1', 'param2'
    मुझे त्रुटि मिलती है:

    कीवर्ड 'exec' के पास गलत वाक्यविन्यास।


(एसक्यूएल सर्वर मानते हैं)

टी-एसक्यूएल में संग्रहीत प्रक्रिया के परिणामों के साथ काम करने का एकमात्र तरीका INSERT INTO ... EXEC का उपयोग करना है INSERT INTO ... EXEC वाक्यविन्यास। यह आपको एक अस्थायी तालिका या तालिका चर में डालने का विकल्प देता है और वहां से आपको आवश्यक डेटा का चयन करने का विकल्प देता है।


SQL सर्वर के लिए, मुझे लगता है कि यह ठीक काम करता है:

एक अस्थायी तालिका बनाएं (या स्थायी तालिका, वास्तव में कोई फर्क नहीं पड़ता), और संग्रहित प्रक्रिया के खिलाफ कथन में डालें। एसपी का परिणाम सेट आपकी तालिका में कॉलम से मेल खाना चाहिए, अन्यथा आपको एक त्रुटि मिल जाएगी।

यहां एक उदाहरण दिया गया है:

DECLARE @temp TABLE (firstname NVARCHAR(30), lastname nvarchar(50));

INSERT INTO @temp EXEC dbo.GetPersonName @param1,@param2;
-- assumption is that dbo.GetPersonName returns a table with firstname / lastname columns

SELECT * FROM @temp;

बस!


इसे प्राप्त करने के लिए, पहले आप नीचे #test_table बनाते हैं:

create table #test_table(
    col1 int,
    col2 int,
   .
   .
   .
    col80 int
)

अब प्रक्रिया निष्पादित करें और #test_table में मान #test_table :

insert into #test_table
EXEC MyStoredProc 'param1', 'param2'

अब आप #test_table से मान प्राप्त #test_table :

select col1,col2....,col80 from #test_table

एक त्वरित हैक एक नया पैरामीटर '@Column_Name' जोड़ना होगा और कॉलिंग फ़ंक्शन कॉलम नाम को पुनर्प्राप्त करने के लिए परिभाषित करेगा। आपके sproc के रिटर्न हिस्से में, यदि आपके पास / else कथन होगा और केवल निर्दिष्ट कॉलम लौटाएंगे, या यदि खाली हो - तो सभी को वापस करें।

CREATE PROCEDURE [dbo].[MySproc]
        @Column_Name AS VARCHAR(50)
AS
BEGIN
    IF (@Column_Name = 'ColumnName1')
        BEGIN
            SELECT @ColumnItem1 as 'ColumnName1'
        END
    ELSE
        BEGIN
            SELECT @ColumnItem1 as 'ColumnName1', @ColumnItem2 as 'ColumnName2', @ColumnItem3 as 'ColumnName3'
        END
END

क्या आपने यह कोशिश की है:

  • एक ऐसा फ़ंक्शन बनाएं जो इस संग्रहीत प्रसंस्करण को कॉल करे
  • उस संग्रहीत प्रसंस्करण से लौटाए गए परिणामों को संग्रहीत करने के लिए कर्सर का उपयोग करें
  • उस कर्सर को लूप करें, ताकि आप उन दो कॉलम को प्रिंट / स्टोर कर सकें जिन्हें आपको अस्थायी तालिका में चाहिए (केवल 2columns के साथ)
  • और उसके बाद परिणामों का चयन करने के लिए उस तालिका का उपयोग करें

जैसा कि इस प्रश्न में उल्लेख किया गया है, संग्रहीत प्रक्रिया को निष्पादित करने से पहले 80 कॉलम अस्थायी तालिका को परिभाषित करना मुश्किल है।

तो इसके आस-पास का दूसरा तरीका संग्रहित प्रक्रिया परिणाम सेट के आधार पर तालिका को पॉप्युलेट करना है।

SELECT * INTO #temp FROM OPENROWSET('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;'
                                   ,'EXEC MyStoredProc')

यदि आपको कोई त्रुटि मिल रही है, तो आपको निम्न क्वेरी निष्पादित करके विज्ञापन वितरित क्वेरी सक्षम करने की आवश्यकता है।

sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO

कॉन्फ़िगरेशन विकल्प बदलने या RECONFIGURE कथन चलाने के लिए दोनों पैरामीटर के साथ sp_configure निष्पादित करने के लिए, आपको ALTER SETTINGS सर्वर-स्तरीय अनुमति दी जानी चाहिए

अब आप जेनरेट टेबल से अपने विशिष्ट कॉलम का चयन कर सकते हैं

SELECT col1, col2
FROM #temp

यदि आप अपनी संग्रहीत प्रक्रिया को संशोधित करने में सक्षम हैं, तो आप आसानी से आवश्यक कॉलम परिभाषाओं को पैरामीटर के रूप में रख सकते हैं और स्वत: निर्मित अस्थायी तालिका का उपयोग कर सकते हैं:

CREATE PROCEDURE sp_GetDiffDataExample
      @columnsStatement NVARCHAR(MAX) -- required columns statement (e.g. "field1, field2")
AS
BEGIN
    DECLARE @query NVARCHAR(MAX)
    SET @query = N'SELECT ' + @columnsStatement + N' INTO ##TempTable FROM dbo.TestTable'
    EXEC sp_executeSql @query
    SELECT * FROM ##TempTable
    DROP TABLE ##TempTable
END

इस मामले में आपको मैन्युअल रूप से एक temp तालिका बनाने की आवश्यकता नहीं है - यह स्वचालित रूप से बनाया गया है। उम्मीद है की यह मदद करेगा।


यदि आप डेटा के मैन्युअल सत्यापन के लिए ऐसा कर रहे हैं, तो आप इसे LINQPad के साथ कर सकते हैं।

लिंककैड में डेटाबेस से कनेक्शन बनाएं और फिर निम्न के जैसा सी # कथन बनाएं:

DataTable table = MyStoredProc (param1, param2).Tables[0];
(from row in table.AsEnumerable()
 select new
 {
  Col1 = row.Field<string>("col1"),
  Col2 = row.Field<string>("col2"),
 }).Dump();

संदर्भ http://www.global-webnet.net/blogengine/post/2008/09/10/LINQPAD-Using-Stored-Procedures-Accessing-a-DataSet.aspx उपयोग- http://www.global-webnet.net/blogengine/post/2008/09/10/LINQPAD-Using-Stored-Procedures-Accessing-a-DataSet.aspx प्रसंस्करण- http://www.global-webnet.net/blogengine/post/2008/09/10/LINQPAD-Using-Stored-Procedures-Accessing-a-DataSet.aspx A- http://www.global-webnet.net/blogengine/post/2008/09/10/LINQPAD-Using-Stored-Procedures-Accessing-a-DataSet.aspx


यह जानना सहायक हो सकता है कि यह इतना मुश्किल क्यों है। एक संग्रहीत प्रक्रिया केवल पाठ (प्रिंट 'टेक्स्ट') लौटा सकती है, या कई तालिकाओं को वापस कर सकती है, या कोई टेबल वापस नहीं लौटा सकता है।

तो कुछ SELECT * FROM (exec sp_tables) Table1 काम नहीं करेगा


यह मेरे लिए काम करता है: (यानी मुझे केवल 30+ के 2 कॉलम की आवश्यकता है sp_help_job द्वारा)

SELECT name, current_execution_status 
FROM OPENQUERY (MYSERVER, 
  'EXEC msdb.dbo.sp_help_job @job_name = ''My Job'', @job_aspect = ''JOB''');  

इससे पहले कि यह काम करेगा, मुझे इसे चलाने की जरूरत है:

sp_serveroption 'MYSERVER', 'DATA ACCESS', TRUE;

.... sys.servers तालिका अद्यतन करने के लिए। (यानी OPENQUERY के भीतर एक आत्म-संदर्भ का उपयोग डिफ़ॉल्ट रूप से अक्षम किया जाता है।)

मेरी सरल आवश्यकता के लिए, मैं लांस के उत्कृष्ट लिंक के ओपनक्वरी सेक्शन में वर्णित किसी भी समस्या में भाग गया।

Rossini, यदि आपको उन इनपुट पैरामीटर को गतिशील रूप से सेट करने की आवश्यकता है, तो OPENQUERY का उपयोग थोड़ा और अधिक स्पष्ट हो जाता है:

DECLARE @innerSql varchar(1000);
DECLARE @outerSql varchar(1000);

-- Set up the original stored proc definition.
SET @innerSql = 
'EXEC msdb.dbo.sp_help_job @job_name = '''[email protected]+''', @job_aspect = N'''[email protected]+'''' ;

-- Handle quotes.
SET @innerSql = REPLACE(@innerSql, '''', '''''');

-- Set up the OPENQUERY definition.
SET @outerSql = 
'SELECT name, current_execution_status 
FROM OPENQUERY (MYSERVER, ''' + @innerSql + ''');';

-- Execute.
EXEC (@outerSql);

मुझे डुप्लिकेट / उपनाम बनाने के लिए sp_addlinkedserver (जैसा कि लांस के लिंक में वर्णित है) का उपयोग कर मौजूदा sys.servers आत्म-संदर्भ सीधे अद्यतन करने के लिए sp_serveroption का उपयोग करने के बीच अंतर (यदि कोई है) के बीच निश्चित नहीं है।

नोट 1: मैं OPENROWSET पर OPENQUERY पसंद करता हूं, यह देखते हुए कि OPENQUERY को proc के भीतर कनेक्शन-स्ट्रिंग परिभाषा की आवश्यकता नहीं होती है।

नोट 2: यह सब करने के बाद: आम तौर पर मैं केवल INSERT का उपयोग करता हूं ... EXEC :) हाँ, यह 10 मिनट अतिरिक्त टाइपिंग है, लेकिन अगर मैं इसकी मदद कर सकता हूं, तो मैं इसके साथ घूमना पसंद नहीं करता:
(ए) उद्धरण के भीतर उद्धरण के भीतर उद्धरण, और
(बी) sys टेबल, और / या स्नीकी स्वयं-संदर्भित लिंक्ड सर्वर सेटअप (यानी इनके लिए, मुझे अपने सभी शक्तिशाली डीबीए को अपने मामले की पुष्टि करने की आवश्यकता है :)

हालांकि इस उदाहरण में, मैं एक INSERT का उपयोग नहीं कर सका ... EXEC निर्माण, क्योंकि sp_help_job पहले से ही एक का उपयोग कर रहा है। ("एक इंसर्ट EXEC कथन को नेस्टेड नहीं किया जा सकता है।")






stored-procedures