2009-01-22 11 views
22

मुख्य समस्या पंक्तियों की अनुक्रमणिका को 1,2,3 में बदलने के बारे में है .. जहां संपर्क-आईडी और प्रकार समान है। लेकिन सभी कॉलम में एक ही डेटा हो सकता है क्योंकि कुछ पूर्व-कर्मचारी गड़बड़ हो जाते हैं और संपर्क-आईडी और टाइप द्वारा सभी पंक्तियों को अपडेट करते हैं। किसी भी तरह ऐसी पंक्तियां होती हैं जो गड़बड़ नहीं होती हैं लेकिन सूचकांक पंक्तियां समान होती हैं। यह कुल अराजकता है।कर्सर के अंदर कर्सर

मैंने बाहरी कर्सर से आने वाले चर के साथ एक आंतरिक कर्सर का उपयोग करने की कोशिश की। लेकिन ऐसा लगता है कि यह आंतरिक कर्सर में फंस गया है।

क्वेरी का एक हिस्सा इस तरह दिखता है:

Fetch NEXT FROM OUTER_CURSOR INTO @CONTACT_ID, @TYPE 
While (@@FETCH_STATUS <> -1) 
BEGIN 
IF (@@FETCH_STATUS <> -2) 

    DECLARE INNER_CURSOR Cursor 
    FOR 
    SELECT * FROM CONTACTS 
    where CONTACT_ID = @CONTACT_ID 
    and TYPE = @TYPE 

    Open INNER_CURSOR 

    Fetch NEXT FROM INNER_CURSOR 
    While (@@FETCH_STATUS <> -1) 
    BEGIN 
    IF (@@FETCH_STATUS <> -2) 

क्या समस्या हो सकती है? @@ FETCH_STATUS संदिग्ध या कुछ है?

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

UPDATE CONTACTS 
SET INDEX_NO = @COUNTER 
where current of INNER_CURSOR 

संपादित करें: यहाँ बड़ी तस्वीर है:

BEGIN TRAN 

DECLARE @CONTACT_ID VARCHAR(15) 
DECLARE @TYPE VARCHAR(15) 
DECLARE @INDEX_NO SMALLINT 
DECLARE @COUNTER SMALLINT 
DECLARE @FETCH_STATUS INT 

DECLARE OUTER_CURSOR CURSOR 

FOR 

SELECT CONTACT_ID, TYPE, INDEX_NO FROM CONTACTS 
WHERE 
CONTACT_ID IN (SELECT CONTACT_ID FROM dbo.CONTACTS 
WHERE CONTACT_ID IN(...) 
GROUP BY CONTACT_ID, TYPE, INDEX_NO 
HAVING COUNT(*) > 1 

OPEN OUTER_CURSOR 

FETCH NEXT FROM OUTER_CURSOR INTO @CONTACT_ID, @TYPE, @INDEX_NO 
WHILE (@@FETCH_STATUS <> -1) 
BEGIN 
IF (@@FETCH_STATUS <> -2) 

SET @COUNTER = 1 

     DECLARE INNER_CURSOR CURSOR 
     FOR 
     SELECT * FROM CONTACTS 
     WHERE CONTACT_ID = @CONTACT_ID 
     AND TYPE = @TYPE 
     FOR UPDATE 

     OPEN INNER_CURSOR 

     FETCH NEXT FROM INNER_CURSOR 

     WHILE (@@FETCH_STATUS <> -1) 
     BEGIN 
     IF (@@FETCH_STATUS <> -2) 

     UPDATE CONTACTS 
     SET INDEX_NO = @COUNTER 
     WHERE CURRENT OF INNER_CURSOR 

     SET @COUNTER = @COUNTER + 1 

     FETCH NEXT FROM INNER_CURSOR 
     END 
     CLOSE INNER_CURSOR 
     DEALLOCATE INNER_CURSOR 

FETCH NEXT FROM OUTER_CURSOR INTO @CONTACT_ID, @TYPE, @INDEX_NO 
END 
CLOSE OUTER_CURSOR 
DEALLOCATE OUTER_CURSOR 

COMMIT TRAN 
+0

एक और सवाल: एसक्यूएल सर्वर का कौन सा संस्करण, क्योंकि यह निर्धारित करेगा कि हम आपके @ काउंटर को आंतरिक कर्सर में बदलने के लिए पंक्ति संख्या बनाने के लिए क्या उपयोग कर सकते हैं। –

+0

क्या आप सेट आधारित तर्क के बारे में जानते हैं? कर्सर को अंतिम उपाय के रूप में उपयोग किया जाना चाहिए ... –

+0

तो क्या आप उत्तर देने के लिए पर्याप्त दयालु हो सकते हैं? अगर आपको स्थिति के बारे में अधिक जानकारी चाहिए, तो मैं खुशी से इसे प्रदान करता हूं। –

उत्तर

-1

मैं पूरी तरह से समझ में नहीं आता क्या "कर्सर का अद्यतन वर्तमान" के साथ समस्या थी लेकिन यह बयान लाने भीतरी कर्सर के लिए दो बार का उपयोग करके हल किया जाता है:

FETCH NEXT FROM INNER_CURSOR 

WHILE (@@FETCH_STATUS <> -1) 
BEGIN 

UPDATE CONTACTS 
SET INDEX_NO = @COUNTER 
WHERE CURRENT OF INNER_CURSOR 

SET @COUNTER = @COUNTER + 1 

FETCH NEXT FROM INNER_CURSOR 
FETCH NEXT FROM INNER_CURSOR 
END 
2

आप किसी भी अधिक फ़ेच करना क्या अगर मैं भीतरी कर्सर के अंदर इस कोड का उपयोग नहीं करते सब कुछ ठीक लग रहा है? आपको उन्हें भी दिखाना चाहिए। आप केवल हमें आधा कोड दिखा रहे हैं।

यह तरह दिखना चाहिए:

FETCH NEXT FROM @Outer INTO ... 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    DECLARE @Inner... 
    OPEN @Inner 
    FETCH NEXT FROM @Inner INTO ... 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
    ... 
    FETCH NEXT FROM @Inner INTO ... 
    END 
    CLOSE @Inner 
    DEALLOCATE @Inner 
    FETCH NEXT FROM @Outer INTO ... 
END 
CLOSE @Outer 
DEALLOCATE @Outer 

इसके अलावा, सुनिश्चित करें कि आप कर्सर एक ही नाम नहीं बना ... और किसी भी कोड (अपने ट्रिगर्स जाँच) कहा जाता हो जाता है कि एक कर्सर कि नाम है का उपयोग नहीं करता वही। मैंने स्टैक के कई परतों में 'कर्सर' का उपयोग करके लोगों से अजीब व्यवहार देखा है।

+0

शेष क्वेरी आपके जैसा वर्णन की तरह दिखती है। कर्सर नाम और fetches ठीक से नामित हैं। –

54

आपके पास कई प्रकार की समस्याएं हैं। सबसे पहले, आप अपने विशिष्ट @@ FETCH_STATUS मानों का उपयोग क्यों कर रहे हैं? यह सिर्फ @@ FETCH_STATUS = 0.

दूसरा, आप अपने आंतरिक कर्सर को में कुछ भी नहीं चुन रहे हैं। और मैं किसी भी परिस्थिति के बारे में नहीं सोच सकता जहां आप इस तरह के सभी क्षेत्रों का चयन करेंगे - उन्हें जादू करें!

यहां जाने के लिए एक नमूना है। फ़ोल्डर में "क्लाइंटिड" की प्राथमिक कुंजी है जो उपस्थित होने के लिए एक विदेशी कुंजी भी है। मैं बस में भाग UIDs के सभी मुद्रण कर रहा हूँ, फ़ोल्डर ClientID के आधार पर विभाजित:

Declare @ClientID int; 
Declare @UID int; 

DECLARE Cur1 CURSOR FOR 
    SELECT ClientID From Folder; 

OPEN Cur1 
FETCH NEXT FROM Cur1 INTO @ClientID; 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    PRINT 'Processing ClientID: ' + Cast(@ClientID as Varchar); 
    DECLARE Cur2 CURSOR FOR 
     SELECT UID FROM Attend Where [email protected]; 
    OPEN Cur2; 
    FETCH NEXT FROM Cur2 INTO @UID; 
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     PRINT 'Found UID: ' + Cast(@UID as Varchar); 
     FETCH NEXT FROM Cur2 INTO @UID; 
    END; 
    CLOSE Cur2; 
    DEALLOCATE Cur2; 
    FETCH NEXT FROM Cur1 INTO @ClientID; 
END; 
PRINT 'DONE'; 
CLOSE Cur1; 
DEALLOCATE Cur1; 

अंत में, आप कर रहे हैं यकीन आप चाहते हैं एक संग्रहीत प्रक्रिया में कुछ इस तरह कर रही हैं? संग्रहित प्रक्रियाओं का दुरुपयोग करना बहुत आसान है और अक्सर आपकी समस्या को दर्शाने में समस्याएं दर्शाता है। उदाहरण के लिए, नमूना मैंने मानक चयन कॉल का उपयोग करके कहीं अधिक आसानी से पूरा किया जा सकता है।

+0

मैं कुछ भी नहीं चुनता क्योंकि मैं सिर्फ आंतरिक कर्सर की वर्तमान पंक्ति को अपडेट करना चाहता था। क्या मुझे @ सोमेरीएबल में उपयोग करना है? –

+0

क्या आपके पास प्रत्येक "Contact_ID" के लिए आपकी संपर्क तालिका में एक से अधिक रिकॉर्ड हैं? यदि ऐसा है, तो आपका "होना" नकली है - यह हमेशा झूठा होगा। यदि नहीं, तो कभी बुरा मत मानो। मैं बस अपना तर्क समझने की कोशिश कर रहा हूं। साथ ही, क्लॉज होने के बाद "बंद" नहीं होना चाहिए? –

+0

यिक्स - आप रिकॉर्ड-दर-रिकॉर्ड आधार पर INDEX_NO फ़ील्ड पर पुन: असाइन कर रहे हैं, लेकिन केवल उन रिकॉर्ड के लिए जहां पुराने INDEX_NO को खाते में लेने के बाद भी गुणक हैं? –

8

आप कर्सर को पूरी तरह से टालने से नेस्टेड कर्सर मुद्दों, सामान्य कर्सर मुद्दों और वैश्विक चर मुद्दों को भी हटा सकते हैं।

declare @rowid int 
declare @rowid2 int 
declare @id int 
declare @type varchar(10) 
declare @rows int 
declare @rows2 int 
declare @outer table (rowid int identity(1,1), id int, type varchar(100)) 
declare @inner table (rowid int identity(1,1), clientid int, whatever int) 

insert into @outer (id, type) 
Select id, type from sometable 

select @rows = count(1) from @outer 
while (@rows > 0) 
Begin 
    select top 1 @rowid = rowid, @id = id, @type = type 
    from @outer 
    insert into @innner (clientid, whatever) 
    select clientid whatever from contacts where contactid = @id 
    select @rows2 = count(1) from @inner 
    while (@rows2 > 0) 
    Begin 
     select top 1 /* stuff you want into some variables */ 
     /* Other statements you want to execute */ 
     delete from @inner where rowid = @rowid2 
     select @rows2 = count(1) from @inner 
    End 
    delete from @outer where rowid = @rowid 
    select @rows = count(1) from @outer 
End 
+0

धन्यवाद बहुत अच्छा उदाहरण! समस्या यह है कि मुझे कर्सर की वर्तमान पंक्ति का उपयोग करना होगा। क्योंकि 2 या अधिक पंक्तियों के बारे में सोचने में बिल्कुल वही डेटा या अलग-अलग डेटा हो सकता है जिसे आप खोने का जोखिम नहीं उठा सकते हैं। इस समाधान के साथ समस्या बाहरी तालिका के साथ डेटा मिलान करना असंभव है। –

2

यह किसी चीज की गंध करता है जो इसके बजाय जॉइन के साथ किया जाना चाहिए। क्या आप हमारे साथ बड़ी समस्या साझा कर सकते हैं?


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

UPDATE [YourTable/Alias] 
    SET [Column] = q.Value 
FROM 
(
    ... complicate select query here ... 
) q 

कहाँ [YourTable/Alias] एक मेज या उर्फ ​​चयन क्वेरी में उपयोग किया है।

0

मैं एक ही था समस्या,

क्या आप दूसरी कर्सर की घोषणा कर रहा है के रूप में क्या करना है: घोषित [second_cursor] स्थानीय कर्सर

के लिए आप के बजाय "कर्सर के लिए" "के लिए कर्सर स्थानीय" देख

+0

LOCAL केवल एक स्कोप संशोधक होना चाहिए जो मौजूदा कनेक्शन स्कोप के लिए वर्तमान प्रक्रिया दायरे में कर्सर उपलब्धता को सीमित करता है। सुनिश्चित नहीं है कि यह उपर्युक्त मुद्दे को कैसे प्रभावित करेगा। – Milan