2009-06-08 12 views
5

मैं मौजूदा कोड में SQL सर्वर कर्सर को प्रतिस्थापित करने के साथ अपने अनुभव को जानना चाहता हूं, या आपने कोई समस्या कैसे उठाई है जो एक प्रक्रियात्मक व्यक्ति कर्सर को हल करने के लिए उपयोग करेगा, और इसे सेट-आधारित किया था।कर्सर को बदलने के विभिन्न तरीके क्या हैं?

कर्सर को हल करने के लिए किस समस्या का उपयोग किया गया था? आपने कर्सर को कैसे बदल दिया?

उत्तर

5

कभी भी लूप करने की कोशिश न करें, डेटा के सेट पर काम करें।

आप एक ही समय में कई पंक्तियों को सम्मिलित, अद्यतन, हटा सकते हैं। यहां कई पंक्तियों के उदाहरण डालने में:

INSERT INTO YourTable 
     (col1, col2, col3, col4) 
    SELECT 
     cola, colb+Colz, colc, @X 
     FROM .... 
      LEFT OUTER JOIN ... 
     WHERE... 

जब एक लूप को देखते हुए देखें कि यह इसके अंदर क्या किया गया है। यदि यह केवल आवेषण/हटाना/अपडेट है, तो एकल आदेशों का उपयोग करने के लिए पुनः लिखें। यदि आईएफ हैं, तो देखें कि क्या वे केस स्टेटमेंट्स या आवेषण/हटाए गए/अपडेट पर कहां स्थित हो सकते हैं। यदि ऐसा है, तो लूप को हटाएं और सेट कमांड का उपयोग करें।

मैंने लूप ले लिए हैं और उन्हें सेट आधारित कमांड के साथ बदल दिया है और निष्पादन समय को मिनटों से कुछ सेकंड तक घटा दिया है। मैंने कई नेस्टेड लूप और प्रक्रिया कॉल के साथ प्रक्रियाएं की हैं और लूप को रखा है (केवल आवेषण/हटाना/अपडेट का उपयोग करना असंभव था), लेकिन मैंने कर्सर को हटा दिया, और कम लॉकिंग/अवरुद्ध और बड़े प्रदर्शन को भी बढ़ावा दिया है। यहाँ दो पाशन तरीकों कि बेहतर कर्सर लूप रहे हैं ...

आप पाश करने के लिए है, एक सेट से अधिक कुछ इस तरह करते हैं:

--this looks up each row for every iteration 
DECLARE @msg VARCHAR(250) 
DECLARE @hostname sysname 

--first select of currsor free loop 
SELECT @hostname= min(RTRIM(hostname)) 
    FROM master.dbo.sysprocesses (NOLOCK) 
    WHERE hostname <> '' 

WHILE @hostname is not null 
BEGIN 
    set @msg='exec master.dbo.xp_cmdshell "net send ' 
     + RTRIM(@hostname) + ' ' 
     + 'testing "' 
    print @msg 
    --EXEC (@msg) 

    --next select of cursor free loop 
    SELECT @hostname= min(RTRIM(hostname)) 
     FROM master.dbo.sysprocesses (NOLOCK) 
     WHERE hostname <> '' 
     and hostname > @hostname 
END 

आप आइटम का एक उचित सेट (नहीं 100,000 अगर) पाश से अधिक आप यह कर सकते हैं करने के लिए:

--this will capture each Key to loop over 
DECLARE @msg VARCHAR(250) 
DECLARE @From int 
DECLARE @To  int 
CREATE TABLE #Rows 
(
    RowID  int not null primary key identity(1,1) 
    ,hostname varchar(100) 
) 

INSERT INTO #Rows 
SELECT DISTINCT hostname 
    FROM master.dbo.sysprocesses (NOLOCK) 
    WHERE hostname <> '' 
SELECT @From=0,@[email protected]@ROWCOUNT 

WHILE @From<@To 
BEGIN 
    SET @[email protected]+1 

    SELECT @msg='exec master.dbo.xp_cmdshell "net send ' 
     + RTRIM(hostname) + ' ' 
     + 'testing "' 
     FROM #Rows WHERE [email protected] 
    print @msg 
    --EXEC (@msg) 
END 
2

ठीक है, अक्सर प्रक्रियात्मक प्रोग्रामिंग के लिए उपयोग किया जाने वाला ऐप देव - आदत से बाहर - एसक्यूएल में भी प्रक्रियात्मक रूप से सबकुछ करने की कोशिश करता है।

अक्सर, सही पैरामीटर के साथ एक चयन कर सकता है - या हो सकता है कि आप एक अद्यतन विवरण से निपट रहे हों।

बिंदु वास्तव में है: आपको सेट ऑपरेशंस में सोचने और अपने आरडीबीएमएस को जो कुछ करना है, उसे बताएं - चरणबद्ध तरीके से इसे कैसे करें।

इस के लिए एक "सही" जवाब देना मुश्किल है ..... आपको इसे लगभग ठोस उदाहरण के साथ दिखाना होगा।

मार्क

0

मैं कुछ कोड है कि एक दिए गए वर्ष से संबंधित वित्तीय डेटा के लिए चल रहा है योग गणना लिखा था। प्रत्येक तिमाही में, मुझे मौजूदा तिमाही के लिए मूल्य को कुल योग को उचित रूप से संभालने के दौरान जोड़ना था ताकि पिछली तिमाही के लिए चलने वाला कुल चालू हो, जब चालू तिमाही के मूल्य शून्य थे।

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

आशा इस मदद करता है,

विधेयक

4

मैं while लूप के साथ कुछ कर्सर बदल दिया है।

DECLARE @SomeTable TABLE 
(
    ID int IDENTITY (1, 1) PRIMARY KEY NOT NULL, 
    SomeNumber int, 
    SomeText varchar 
) 

DECLARE @theCount int 
DECLARE @theMax int 

DECLARE @theNumber int 
DECLARE @theText varchar 

INSERT INTO @SomeTable (SomeNumber, SomeText) 
SELECT Number, Text 
FROM PrimaryTable 

SET @theCount = 1 
SELECT @theMax = COUNT(ID) FROM @SomeTable 

WHILE (@theCount <= @theMax) 
BEGIN 

    SET @theNumber = 0 
    SET @theText = '' 

    SELECT @theNumber = IsNull(Number, 0), @theText = IsNull(Text, 'nothing') 
    FROM @SomeTable 
    WHERE ID = @theCount 

    -- Do something. 
    PRINT 'This is ' + @theText + ' from record ' + CAST(@theNumber AS varchar) + '.' 

    SET @theCount = @theCount + 1 

END 

PRINT 'Done' 
संबंधित मुद्दे