2013-09-16 7 views
13

की प्रत्येक पंक्ति के लिए कोड निष्पादित करें क्या किसी भी प्रकार किसी कर्सर का उपयोग किये बिना किसी भी चयन के लिए कुछ कोड निष्पादित करना संभव है?टीएसक्यूएल - एक चुनिंदा

मेरे मामले में: मेरे पास एक जटिल स्क्रिप्ट के लिए कुछ डेटा स्टोर करने के लिए एक temp तालिका है। अंत में मैं आउटपुट में इस तालिका (कुछ शर्तों से सीमित) की कुछ जानकारी पेंट करना चाहता हूं।

वर्तमान में मैं तालिका के पंक्तियों को सीमित करने के लिए चयन के साथ एक कर्सर का उपयोग कर रहा हूं। इस कर्सर में मैं आउटपुट उत्पन्न करने के लिए

print '...' 

का उपयोग कर रहा हूं।

इस तरह के काम करने के लिए एक आसान तरीका होना चाहिए ...

संपादित करें:

create table #tmpAttributes(AttributeId uniqueidentifier, Value float, ValueString nvarchar(max), ActionId uniqueidentifier) 

insert into #tmpAttributes (AttributeId, Value, ValueString, ActionId) 
    select ID,..... -- in this select i'm doing some value conversions, if conversion is not possible i'm using -1 

insert into ActionAttribute (ActionDefinitionID, Discriminator, ID, ReferredActionID, ValueDate, ValueListID, ValueMoney, ValueString, ValueUserID) 
    select @defId, 'ActionAttributeMoneyEntity', NEWID(), ActionId, null, null, Value, null, null from #tmpAttributes 

-- afterwards there is this cursor where I'm printint all rows where Value = -1 
+2

पर्याप्त जानकारी नहीं है।आप वास्तव में क्या हासिल करने की कोशिश कर रहे हैं? यदि आप हमें पूरा परिदृश्य देते हैं तो आपको लगता है कि आपको जो चाहिए वह करने का एक पूरी तरह से सेट-आधारित तरीका है। – gvee

+0

आप 'temp table' पर एक अतिरिक्त पहचान कॉलम क्यों नहीं डालते हैं जिसे आपने पहले ही बनाया है और प्रत्येक पंक्ति के लिए लूप। –

+0

यदि आप केवल अंत में उन सूचनाओं को प्रिंट करना चाहते हैं तो आपको कर्सर की आवश्यकता क्यों है? – DrCopyPaste

उत्तर

19

एक परिणाम काफी सेट में प्रत्येक पंक्ति के लिए एक प्रिंट बयान निष्पादित एक कर्सर या इस

के लिए इसी तरह एक दृष्टिकोण की आवश्यकता है
declare @id int, @stuff varchar(20) 
declare @tmp table 
(
    id int not null 
, stuff varchar(20) 

    primary key(id) 
) 

insert @tmp 
select id, stuff from mastertable 
where condition1 > condition2 

select top 1 @id=id, @stuff=stuff from @tmp 

while (@@rowcount > 0) 
begin 
    print @stuff 
    delete from @tmp where [email protected] 
    select top 1 @id=id, @stuff=stuff from @tmp 
end 

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

पर आधारित पुनरावृत्ति आप केवल पंक्ति प्रसंस्करण द्वारा पंक्ति से बच सकते हैं यदि आप एक सेट-आधारित ऑपरेशन कर सकते हैं। यह देखने के लिए आपके प्रश्न में पर्याप्त जानकारी नहीं है कि यह टीएसक्यूएल

अब से अधिक है, तो एक सीएलआर प्रोसेस लिखना अधिक लचीला हो सकता है क्योंकि आपके पास एक अधिक समृद्ध प्रोग्रामिंग मॉडल है, और प्रत्येक पंक्ति के माध्यम से लूपिंग करने के लिए थोड़ा ओवरहेड है सीएलआर proc के भीतर परिणाम सेट। प्रत्येक पंक्ति के लिए सीएलआर प्रो से डेटाबेस कॉल करना, जो कि प्रत्येक पंक्ति से डेटाबेस कॉल को TSQL

संपादित करें - मुझे लगता है कि किसी ने पहले से ही प्रिंट स्टेटमेंट्स को एक सेट उन्मुख ऑपरेशन में परिवर्तित करने के लिए एक संभावित तरीका जोड़ा है। यानी

declare @msg varchar(max) 
select @msg = '' 

select msg = @msg + stuff 
from mastertable where condition1 > condition2 

print @msg 

यह ठीक है, वास्तव में यह सही है कि जब मैं एक सेट ऑपरेशन करने के लिए कह रहा था तो मैं इष्टतम था। जब संभव हो तो एक सेट आधारित ऑपरेशन हमेशा पसंद किया जाता है। यह स्पष्ट नहीं हो सकता है, लेकिन यदि कई पंक्तियां शामिल हैं तो स्ट्रिंग कॉन्सटेनेशन भी इस उदाहरण में बहुत धीमी हो सकती है।


मैंने कहा कि एक temp var का उपयोग टेबल लॉकिंग से बचाता है। यह बिल्कुल सही नहीं है क्योंकि SQL सर्वर tempdb में किसी तालिका में temp vars लिखता है। मेरा वास्तव में क्या मतलब था कि आप उत्पादन तालिका को लॉक करने से बचते हैं और चूंकि आपको इस तालिका का एकमात्र उपयोगकर्ता होने की गारंटी है, इसलिए आप समवर्ती पहुंच के लिए प्रतिस्पर्धा नहीं करते हैं।

मैंने इसे अनुकूलित करने का कोई भी प्रयास नहीं किया। उदाहरण के लिए, आंतरिक पाश आईडी को ट्रैक कर सकता है और कहां स्थित हो जाता है जहां id> @id (आप आईडी पर परिभाषित प्राथमिक कुंजी भी चाहते हैं)। चूंकि प्रत्येक लूप पुनरावृत्ति के दौरान अस्थायी तालिका अद्यतन नहीं होती है, इसलिए मैं अपेक्षा करता हूं कि यह तेज़ी से हो।

+0

अभी भी एक पाश लेकिन "भारी" कर्सर का उपयोग किए बिना। धन्यवाद! –

8

मैं तुम्हें और अधिक विस्तार देने की आवश्यकता लगता है, लेकिन आप की तरह कुछ की तलाश में हो सकता है:

declare @msg varchar(max)=''; 

select @msg = @msg + 'Output line: ' + ColumnA + ' -- ' + 'ColumnB' + char(13)+char(10) 
from #temp 
where ... 
; 

print @msg; 
+0

तो प्रत्येक पंक्ति के लिए चर के मूल्य को बढ़ाया जाएगा ... अच्छा विचार! –

+0

समांतरता को रोकने के लिए 'विकल्प (MAXDOP 1)' जोड़ना सुनिश्चित करें, जो अप्रत्याशित परिणाम देगा। – gjvdkamp