2008-09-12 14 views
36

मैं SQL सर्वर 2005 का उपयोग कर रहा हूं, और मैं जानना चाहता हूं कि ट्रांसएक्ट-एसक्यूएल के भीतर से विभिन्न परिणाम सेट कैसे प्राप्त करें। निम्नलिखित संग्रहीत प्रक्रिया दो परिणाम सेट लौटाती है, उदाहरण के लिए, मैं उन्हें कैसे एक्सेस करूं, उदाहरण के लिए, एक और संग्रहीत प्रक्रिया?संग्रहित प्रक्रियाओं के भीतर से परिणाम सेट तक पहुंच ट्रांजैक्ट-एसक्यूएल एसक्यूएल सर्वर

CREATE PROCEDURE getOrder (@orderId as numeric) AS 
BEGIN 
    select order_address, order_number from order_table where order_id = @orderId 
    select item, number_of_items, cost from order_line where order_id = @orderId 
END 

मुझे व्यक्तिगत रूप से दोनों परिणाम सेटों के माध्यम से पुन: प्रयास करने में सक्षम होना चाहिए।

संपादित करें: बस प्रश्न को स्पष्ट करने के लिए, मैं संग्रहित प्रक्रियाओं का परीक्षण करना चाहता हूं। मेरे पास संग्रहित प्रक्रियाओं का एक सेट है जिसका उपयोग VB.NET क्लाइंट से किया जाता है, जो एकाधिक परिणाम सेट लौटाता है। इन्हें एक टेबल मूल्यवान फ़ंक्शन में बदला नहीं जा रहा है, मैं वास्तव में प्रक्रियाओं को बिल्कुल बदल नहीं सकता हूं। प्रक्रिया को बदलना एक विकल्प नहीं है।

प्रक्रियाओं द्वारा लौटाए गए परिणाम सेट समान डेटा प्रकार या स्तंभों की संख्या नहीं हैं।

उत्तर

34

संक्षिप्त उत्तर यह है: आप इसे नहीं कर सकते हैं।

टी-एसक्यूएल से, नेस्टेड संग्रहीत प्रक्रिया कॉल के कई परिणामों तक पहुंचने का कोई तरीका नहीं है, संग्रहीत प्रक्रिया को बदले बिना दूसरों ने सुझाव दिया है।

पूरा होने के लिए, यदि प्रक्रिया एकल परिणाम लौटने रहे थे, तो आप इसे एक अस्थायी तालिका या निम्न सिंटैक्स के साथ तालिका चर में सम्मिलित हो सकते हैं:

INSERT INTO #Table (...columns...) 
EXEC MySproc ...parameters... 

आप एक प्रक्रिया के लिए एक ही वाक्य विन्यास का उपयोग कर सकते हैं कि कई परिणाम देता है, लेकिन यह केवल पहले परिणाम को संसाधित करेगा, शेष को त्याग दिया जाएगा।

+2

मैंने अभी ब्रैनन के समाधान का परीक्षण किया है, और वास्तव में, यदि संग्रहीत प्रक्रिया के भीतर सभी प्रश्न कॉलम और डेटा प्रकारों की समान संख्या लौटाते हैं, तो परिणाम सेट में परिणाम सेट का एक संघ शामिल होगा। जो बहुत बेकार है। आपकी मदद के लिए धन्यवाद। –

0

आप उन्हें टेम्पलेट टेबल में चुन सकते हैं या परिणाम सेट वापस करने के लिए तालिका मूल्यवान फ़ंक्शंस लिख सकते हैं। परिणाम सेट के माध्यम से पुन: प्रयास करने के लिए पूछ रहे हैं?

1

इसे आसानी से करने के दो तरीके हैं। या तो परिणामों को एक temp तालिका में चिपकाएं और फिर अपने sproc से temp तालिका का संदर्भ लें। दूसरा विकल्प परिणाम को एक्सएमएल वैरिएबल में डालना है जिसे ओयूटीपीयूटी वैरिएबल के रूप में उपयोग किया जाता है।

हालांकि, इन दोनों विकल्पों में पेशेवरों और विपक्ष हैं। एक अस्थायी तालिका के साथ, आपको उस स्क्रिप्ट में कोड जोड़ना होगा जो प्रक्रिया को संशोधित करने से पहले अस्थायी तालिका बनाने के लिए कॉलिंग प्रक्रिया बनाता है। इसके अलावा, आपको प्रक्रिया के अंत में अस्थायी तालिका को साफ करना चाहिए।

एक्सएमएल के साथ, यह स्मृति गहन और धीमी हो सकती है।

4

ध्यान दें कि INSERT में एक अतिरिक्त, अनियंत्रित सीमा है ... EXEC कथन: इसे घोंसला नहीं किया जा सकता है। यही है, संग्रहित proc जिसे EXEC कॉल करता है (या जो भी इसे बदले में कॉल करता है) स्वयं ही एक इंसर्ट नहीं कर सकता ... EXEC। ऐसा प्रतीत होता है कि प्रति प्रक्रिया में एक स्क्रैचपैड है जो परिणाम जमा करता है, और यदि वे घोंसले में हैं तो कॉलर इसे खोलने पर आपको एक त्रुटि मिल जाएगी, और फिर कैली इसे फिर से खोलने का प्रयास करता है।

मैथ्यूयू, आपको परिणाम के प्रत्येक "प्रकार" के लिए अलग-अलग temp तालिकाओं को बनाए रखने की आवश्यकता होगी। साथ ही, यदि आप एक ही बार कई बार निष्पादित कर रहे हैं, तो आपको उस परिणाम के लिए एक अतिरिक्त कॉलम जोड़ने की आवश्यकता हो सकती है जिससे यह इंगित किया जा सके कि यह किस कॉल से हुआ था।

2

अफसोस की बात यह है कि ऐसा करना असंभव है। समस्या यह है कि, यह अनुमति देने के लिए कोई एसक्यूएल सिंटेक्स नहीं है। यह निश्चित रूप से 'हुड के नीचे' होता है, लेकिन आप इन अन्य परिणामों को टीएसक्यूएल में नहीं प्राप्त कर सकते हैं, केवल ओडीबीसी या जो भी हो, के माध्यम से।

अधिकांश चीजों के साथ, इसके चारों ओर एक रास्ता है। चाल एक एएसओडीबी ऑब्जेक्ट बनाने के लिए टीएसक्यूएल में ओले ऑटोमेशन का उपयोग करना है जो प्रत्येक परिणामसेट को बदले में खोलता है और परिणामों को आपके द्वारा नामांकित टेबल पर लिखता है (या जो भी आप परिणाम के साथ चाहते हैं)। यदि आप दर्द का आनंद लेते हैं तो आप इसे डीएमओ में भी कर सकते हैं।

8

मैं SQL2005 सीएलआर संग्रहीत प्रक्रिया बनाकर ऐसा करने में आसानी से ऐसा करने में सक्षम था जिसमें एक आंतरिक डेटासेट था।

आप देखते हैं, एक नया SqlDataAdapter होगा। डिफ़ॉल्ट रूप से एक बहु-तालिका डेटासेट में एकाधिक-परिणाम-सेट स्पोक करें। इन तालिकाओं में डेटा को कॉलिंग स्पोक में # टेम्पलेट टेबल में डाला जा सकता है जिसे आप लिखना चाहते हैं। डेटासेट। ReadXmlSchema आपको प्रत्येक परिणाम सेट की स्कीमा दिखाएगा।

चरण 1: sproc जो बहु परिणाम सेट sproc

एक से डेटा पढ़ने जाएगा लेखन शुरू करो। स्कीमा के अनुसार प्रत्येक परिणाम सेट के लिए एक अलग तालिका बनाएं।

CREATE PROCEDURE [dbo].[usp_SF_Read] AS 
SET NOCOUNT ON; 
CREATE TABLE #Table01 (Document_ID VARCHAR(100) 
    , Document_status_definition_uid INT 
    , Document_status_Code VARCHAR(100) 
    , Attachment_count INT 
    , PRIMARY KEY (Document_ID)); 

बी।

चरण 2:: इस बिंदु पर आप एक कर्सर घोषित करने के लिए बार-बार CLR sproc तुम यहाँ पैदा करेगा कॉल करने के लिए आवश्यकता हो सकती है CLR sproc

Partial Public Class StoredProcedures 
    <Microsoft.SqlServer.Server.SqlProcedure()> _ 
    Public Shared Sub usp_SF_ReadSFIntoTables() 

    End Sub 
End Class 

एक बनाओ। New SqlConnection("context connection=true") का उपयोग कर कनेक्ट करें।

बी। एकाधिक-परिणाम-सेट स्पोक रखने के लिए एक कमांड ऑब्जेक्ट (cmd) सेट अप करें।

सी। निम्नलिखित का उपयोग कर सभी डेटा प्राप्त करें:

Dim dataset As DataSet = New DataSet 
    With New SqlDataAdapter(cmd) 
     .Fill(dataset) ' get all the data. 
    End With 
'you can use dataset.ReadXmlSchema at this point... 

डी। प्रत्येक तालिका पर Iterate और प्रत्येक पंक्ति को उपयुक्त temp तालिका में डालें (जिसे आपने उपरोक्त चरण में बनाया है)।

अंतिम नोट: मेरे अनुभव में, आप तो आप जानते हैं जो बैच प्रत्येक रिकॉर्ड से आया है अपने तालिकाओं के बीच कुछ रिश्तों को लागू करने की इच्छा हो सकती है।

यह सब कुछ था!

~ शॉन पास सिएटल

+0

जबकि एसक्यूएलसीएलआर वास्तव में इस समस्या को हल करने का एकमात्र तरीका है, तो 'डेटासेट' पर डंपिंग का आसान मार्ग _not_ स्केलेबल है क्योंकि सभी परिणाम सेट के सभी परिणाम स्मृति में होंगे। अधिक उपयुक्त/स्केलेबल विधि 'SqlDataReader' पर पुनरावृत्ति करना है और प्रत्येक पंक्ति को' SqlDataReader' से पढ़ा जाता है। @ डैनराडु का जवाब यहां, सभी डेटाटाइप (एक फिक्स करने योग्य लघु आने) को संभालने के बाहर, प्रत्येक पंक्ति को पढ़ने के रूप में भेजता है: http://stackoverflow.com/questions/6388489/insert-into-temp-table-from-a -stored-प्रक्रिया-कि-रिटर्न-बहु-परिणाम सेट/11045189 # 11045189 –

5

एक kludge है कि आप भी कर सकते हैं नहीं है। अपने sproc के लिए एक वैकल्पिक पैरामीटर एन int जोड़ें। डिफ़ॉल्ट रूप से एन -1 के मान। यदि एन का मान -1 है, तो अपने चयन में से प्रत्येक को करें। अन्यथा, एनथ चयन करें और केवल एनएच का चयन करें।

उदाहरण के लिए

,

if (N = -1 or N = 0) 
    select ... 

if (N = -1 or N = 1) 
    select ... 

अपने sproc की कॉल जो एन निर्दिष्ट नहीं करते हैं एक परिणाम के एक से अधिक तालिकाओं के साथ सेट मिल जाएगा। यदि आपको किसी अन्य स्पोक से इन तालिकाओं में से एक या अधिक निकालने की आवश्यकता है, तो बस एन के लिए एक मान निर्दिष्ट करने वाले अपने स्पोक को कॉल करें। आपको प्रत्येक तालिका के लिए एक बार स्पोक को कॉल करना होगा जिसे आप निकालना चाहते हैं। अक्षम होने पर आपको परिणाम सेट से एक से अधिक तालिका की आवश्यकता होती है, लेकिन यह शुद्ध TSQL में काम करता है।

संबंधित मुद्दे