2009-05-20 4 views
163

मेरे पास एक संग्रहीत प्रक्रिया है जो उपयोगकर्ता डेटा को एक निश्चित तरीके से बदल देती है। मैं इसे user_id पास करता हूं और यह बात करता है। मैं एक टेबल पर एक क्वेरी चलाने के लिए चाहता हूं और फिर प्रत्येक user_id के लिए मुझे उस उपयोगकर्ता_idक्वेरी द्वारा लौटाई गई प्रत्येक पंक्ति के लिए एक बार संग्रहित प्रक्रिया को कैसे निष्पादित किया जाए?

पर संग्रहीत प्रक्रिया को चलाने के लिए मिलता है, मैं इसके लिए क्वेरी कैसे लिखूं?

+5

आप की जरूरत है यह निर्दिष्ट करने के लिए कि आरडीबीएमएस क्या है - एसक्यूएल सर्वर, ओरेकल, माईएसक्ल, आदि के लिए उत्तर अलग होगा –

+5

संभावना है कि आपको किसी संग्रहीत प्रक्रिया की आवश्यकता नहीं है। क्या आप संग्रहीत प्रक्रिया को "क्या" रूपरेखा कर सकते हैं, बिल्कुल? शायद पूरी प्रक्रिया को एक अद्यतन कथन के रूप में व्यक्त किया जा सकता है। यदि संभव हो तो "प्रत्येक रिकॉर्ड के लिए एक बार करें" पैटर्न को आम तौर पर टालना चाहिए। – Tomalak

+0

आप किस डेटाबेस का उपयोग कर रहे हैं? –

उत्तर

196

एक कर्सर का उपयोग

परिशिष्ट: [एमएस एसक्यूएल कर्सर उदाहरण]

declare @field1 int 
declare @field2 int 
declare cur CURSOR LOCAL for 
    select field1, field2 from sometable where someotherfield is null 

open cur 

fetch next from cur into @field1, @field2 

while @@FETCH_STATUS = 0 BEGIN 

    --execute your sproc on each row 
    exec uspYourSproc @field1, @field2 

    fetch next from cur into @field1, @field2 
END 

close cur 
deallocate cur 
एमएस एसक्यूएल में

, here's an example article

ध्यान दें कि कर्सर सेट आधारित संचालन की तुलना में धीमी है, लेकिन तेजी से मार्गदर्शन से जबकि-छोरों; अधिक जानकारी in this SO question

अतिरिक्त 2: यदि आप केवल कुछ रिकॉर्ड से अधिक प्रसंस्करण करेंगे, तो उन्हें पहले एक अस्थायी तालिका में खींचें और कर्सर को अस्थायी तालिका पर चलाएं; यह एसक्यूएल को टेबल-लॉक में बढ़ने से रोक देगा और ऑपरेशन तेज करेगा

अतिरिक्त 3: और निश्चित रूप से, यदि आप प्रत्येक उपयोगकर्ता आईडी में जो भी संग्रहीत प्रक्रिया कर रहे हैं, और पूरी चीज को एक एकल SQL अद्यतन कथन के रूप में चलाएं, , यह इष्टतम

+0

विस्तार करने के लिए देखभाल? – BigOmega

+0

@ [रयान]: परिशिष्ट देखें। –

+0

कीवर्ड 'करीबी' के पास गलत वाक्यविन्यास? – BigOmega

7

आपकी तालिकाओं और फ़ील्ड नामों के लिए इस प्रतिस्थापन की आवश्यकता होगी।

Declare @TableUsers Table (User_ID, MyRowCount Int Identity(1,1) 
Declare @i Int, @MaxI Int, @UserID nVarchar(50) 

Insert into @TableUser 
Select User_ID 
From Users 
Where (My Criteria) 
Select @MaxI = @@RowCount, @i = 1 

While @i <= @MaxI 
Begin 
Select @UserID = UserID from @TableUsers Where MyRowCount = @i 
Exec prMyStoredProc @UserID 
Select 

@i = @i + 1, @UserID = null 
End 
+2

जबकि लूप कर्सर से धीमे होते हैं –

+0

घोषित कर्सर एसक्यूएल निर्माण या कथन समर्थित नहीं है (??) – BigOmega

46

यदि आपको लूप की आवश्यकता है तो अपनी विधि बदलने की कोशिश करें!

अभिभावक संग्रहीत प्रक्रिया के भीतर, एक #temp तालिका बनाएं जिसमें उस प्रक्रिया को शामिल किया गया है जिसे आपको संसाधित करने की आवश्यकता है। बच्चे संग्रहीत प्रक्रिया को कॉल करें, #temp तालिका दिखाई देगी और आप इसे संसाधित कर सकते हैं, आशा है कि डेटा के पूरे सेट और कर्सर या लूप के बिना काम कर रहे हों।

यह वास्तव में इस बच्चे की संग्रहीत प्रक्रिया क्या कर रहा है इस पर निर्भर करता है। यदि आप अद्यतन कर रहे हैं, तो आप #temp तालिका में शामिल होने से "अपडेट" कर सकते हैं और लूप के बिना एक ही कथन में सभी काम कर सकते हैं। INSERT और DELETEs के लिए भी किया जा सकता है। यदि आपको आईएफ के साथ कई अपडेट करने की आवश्यकता है तो आप उन्हें #temp तालिका के साथ एकाधिक UPDATE FROM में परिवर्तित कर सकते हैं और केस स्टेटमेंट या कहां स्थितियों का उपयोग कर सकते हैं।

डेटाबेस में काम करते समय लूपिंग की मानसिकता खोने का प्रयास करें, यह वास्तविक प्रदर्शन नाली है, जिससे लॉकिंग/अवरुद्ध हो जाएगा और प्रसंस्करण धीमा हो जाएगा। यदि आप हर जगह लूप करते हैं, तो आपका सिस्टम बहुत अच्छी तरह से स्केल नहीं करेगा, और धीमे रीफ्रेश के बारे में शिकायत करने पर उपयोगकर्ताओं को तेज़ करना बहुत कठिन होगा।

इस प्रक्रिया की सामग्री पोस्ट करें जिसे आप लूप में कॉल करना चाहते हैं, और मैं 10 बार में से 9 शर्त लगाऊंगा, आप इसे पंक्तियों के सेट पर काम करने के लिए लिख सकते हैं।

+4

यदि मैं – HLGEM

+2

+1 बहुत अच्छे कामकाज के लिए कर सकता हूं, तो मुझे लगता है कि आप बच्चे के स्पोक को नियंत्रित करते हैं –

+0

थोड़ा सोच, यह सोल्ल्यूशन बहुत बेहतर है! – encc

4

क्या यह आपके द्वारा संग्रहीत प्रक्रिया को जो कुछ भी कर रहा है उसे दोहराने के लिए उपयोगकर्ता द्वारा परिभाषित फ़ंक्शन के साथ नहीं किया जा सकता है?

SELECT udfMyFunction(user_id), someOtherField, etc FROM MyTable WHERE WhateverCondition 

जहां udfMyFunction एक समारोह आपको लगता है कि बनाने में यूजर आईडी लेता है और जो कुछ भी आप इसके साथ क्या करने की जरूरत है।

में थोड़ा और अधिक पृष्ठभूमि

के लिए http://www.sqlteam.com/article/user-defined-functions देखें मैं मानता हूँ कि कर्सर वास्तव में जहां संभव से बचा जाना चाहिए। और यह आमतौर पर संभव है!

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

+1

ओपी: "संग्रहीत प्रक्रिया जो उपयोगकर्ता डेटा को किसी निश्चित तरीके से बदलती है" [एमएसडीएन] (http://technet.microsoft.com/en-us/library/ms191320.aspx): उपयोगकर्ता-परिभाषित फ़ंक्शंस का प्रदर्शन करने के लिए उपयोग नहीं किया जा सकता क्रियाएँ जो डेटाबेस स्थिति को संशोधित करती हैं। हालांकि SQLSVR 2014 में कोई समस्या नहीं है –

3

आप इसे गतिशील क्वेरी के साथ कर सकते हैं।

declare @cadena varchar(max) = '' 
select @cadena = @cadena + 'exec spAPI ' + ltrim(id) + ';' 
from sysobjects; 
exec(@cadena); 
1

मुझे डेव रिंकॉन के गतिशील क्वेरी तरीके पसंद हैं क्योंकि यह कर्सर का उपयोग नहीं करता है और यह छोटा और आसान है। साझा करने के लिए डेव धन्यवाद।

लेकिन Azure एसक्यूएल पर और एक "अलग" क्वेरी में साथ मेरी जरूरतों के लिए, मैं इस तरह कोड को संशोधित करने के लिए किया था:

Declare @SQL nvarchar(max); 
-- Set SQL Variable 
-- Prepare exec command for each distinctive tenantid found in Machines 
SELECT @SQL = (Select distinct 'exec dbo.sp_S2_Laser_to_cache ' + 
       convert(varchar(8),tenantid) + ';' 
       from Dim_Machine 
       where iscurrent = 1 
       FOR XML PATH('')) 

--for debugging print the sql 
print @SQL; 

--execute the generated sql script 
exec sp_executesql @SQL; 

मुझे आशा है कि यह किसी को मदद करता है ...

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

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