2009-05-22 10 views
7

मेरे पास आ कर्सर पाश है कि एक तालिका की सामग्री एक साथ श्रृंखलाबद्ध, इन पंक्तियों के साथ कोड का उपयोग करके एक स्ट्रिंग के निर्माण है:ओरेकल कर्सर अंतिम आइटम के माध्यम से चल दो बार

OPEN cur_t; 
LOOP 
    FETCH cur_t INTO v_texttoadd; 

    v_string := v_string || v_texttoadd; 
EXIT WHEN cur_t%notfound; 
END LOOP; 

समस्या है, ज़ाहिर है, कि आखिरी वस्तु दो बार जोड़ दी जाती है क्योंकि यह समझने से पहले सिस्टम एक बार फिर से चलता है कि खोजने के लिए और कुछ नहीं है।

मैं की तरह

OPEN cur_t; 
WHILE cur_t%found; 
LOOP 
    FETCH cur_t INTO v_texttoadd; 

    v_string := v_string || v_texttoadd; 
END LOOP; 

कुछ के साथ प्रयोग करना करने की कोशिश की लेकिन वह कुछ भी वापस जाने के लिए नहीं मालूम था।

मैं किस प्रकार का वाक्यविन्यास उपयोग कर रहा हूं ताकि प्रत्येक पंक्ति केवल परिणामस्वरूप स्ट्रिंग में दिखाई दे?

उत्तर

21

आप इस कोशिश कर सकते हैं:

OPEN cur_t; 
LOOP 
    FETCH cur_t INTO v_texttoadd; 
    EXIT WHEN cur_t%notfound; 
    v_string := v_string || v_texttoadd; 
END LOOP; 

यह काम करता है% notfound जब सेट कर दिया जाता FETCH निष्पादित किया जाता है और वहाँ किसी भी अधिक पंक्तियों को लाने के लिए नहीं कर रहे हैं क्योंकि। आपके उदाहरण में आपने concatenation के बाद% notfound की जांच की और नतीजतन, आपके पास अंत में डुप्लिकेट था।

+0

मेरे लिए काम नहीं किया। यदि आप परवाह करते हैं तो मेरे उत्तर पर नज़र डालें। –

0

सरल जवाब है, हालांकि संभवतः नहीं सबसे अच्छा:

OPEN cur_t; 
LOOP 
    FETCH cur_t INTO v_texttoadd; 
    IF cur_t%found THEN 
     v_string := v_string || v_texttoadd; 
    END IF; 
EXIT WHEN cur_t%notfound; 
END LOOP; 
+0

मुझे लगता है कि, आपके इंडेंटिंग के आधार पर, आप मानते हैं कि EXIT कथन लूप वाक्यविन्यास का हिस्सा है और लूप के अंत में आना चाहिए। यह सच नहीं है; एक्स्टिट लूप के शरीर में किसी अन्य की तरह सिर्फ एक बयान है। यही कारण है कि, जैसा कि अन्य ने दिखाया है, आप इसे अपने मुद्दे को हल करने के लिए तुरंत FETCH के बाद रख सकते हैं। –

+0

मेरे लिए काम नहीं किया था। यदि आप परवाह करते हैं तो मेरे उत्तर पर नज़र डालें। –

2

% notfound जब सेट कर दिया जाता लाने एक नई पंक्ति को पुनः प्राप्त करने में विफल रहता है।

एक और संभव तरीके से (यह एक "अगर" s और "बाहर निकलें जब" रों परहेज):

OPEN cur_t; 
FETCH cur_t INTO v_texttoadd; 
WHILE cur_t%found LOOP 
    v_string := v_string || v_texttoadd; 
    FETCH cur_t INTO v_texttoadd; 
END LOOP; 
+0

मुझे डर है कि यह केवल * सही * सही उत्तर है! के लिए –

3

सही जवाब पहले से ही दी जा चुकी है, लेकिन सिर्फ एक सा व्याख्या।

SQL> declare 
    2 cursor cur_t 
    3 is 
    4 select ename 
    5  from emp 
    6  where deptno = 10 
    7 ; 
    8 v_texttoadd emp.ename%type; 
    9 v_string varchar2(100); 
10 begin 
11 open cur_t; 
12 loop 
13  fetch cur_t into v_texttoadd; 
14  v_string := v_string || v_texttoadd; 
15  exit when cur_t%notfound; 
16 end loop 
17 ; 
18 dbms_output.put_line(v_string); 
19 end; 
20/
CLARKKINGMILLERMILLER 

PL/SQL-procedure is geslaagd. 

यहाँ मिलर दो बार छपा है:

आपकी वर्तमान स्थिति का अनुकरण करना।

SQL> declare 
    2 cursor cur_t 
    3 is 
    4 select ename 
    5  from emp 
    6  where deptno = 10 
    7 ; 
    8 v_texttoadd emp.ename%type; 
    9 v_string varchar2(100); 
10 begin 
11 open cur_t; 
12 loop 
13  fetch cur_t into v_texttoadd; 
14  exit when cur_t%notfound; 
15  v_string := v_string || v_texttoadd; 
16 end loop 
17 ; 
18 dbms_output.put_line(v_string); 
19 end; 
20/
CLARKKINGMILLER 

PL/SQL-procedure is geslaagd. 

हालांकि, अपने PL/SQL कोड जब एक कर्सर के लिए पाश का उपयोग कर आसान हो जाता है: बस बाहर निकलें बयान और v_string काम स्विच करके, आप इच्छित परिणाम मिलता है। तब आप अपने पाश कम हो जाती है में v_texttoadd चर और लाइनों की संख्या को छोड़ सकते हैं:

SQL> declare 
    2 cursor cur_t 
    3 is 
    4 select ename 
    5  from emp 
    6  where deptno = 10 
    7 ; 
    8 v_string varchar2(100); 
    9 begin 
10 for r in cur_t 
11 loop 
12  v_string := v_string || r.ename; 
13 end loop 
14 ; 
15 dbms_output.put_line(v_string); 
16 end; 
17/
CLARKKINGMILLER 

PL/SQL-procedure is geslaagd. 

तुम भी काम पूरा करने के लिए सीधे एसक्यूएल उपयोग कर सकते हैं। एसक्यूएल मॉडल खंड के साथ एक उदाहरण है, अगर आप 10g संस्करण या उच्चतर पर हैं:

SQL> select string 
    2 from (select string 
    3    , rn 
    4    from emp 
    5   where deptno = 10 
    6   model 
    7     dimension by (rownum rn) 
    8     measures (ename, cast(null as varchar2(100)) string) 
    9     (string[any] order by rn desc = ename[cv()] || string[cv()+1] 
10     ) 
11  ) 
12 where rn = 1 
13/

STRING 
----------------------------------------------------------------------------------- 
CLARKKINGMILLER 

1 rij is geselecteerd. 

सादर, रोब।

+0

+1 .. IN ... लूप सुझाव और उदाहरण। लूप के लिए कर्सर आपके मित्र हैं ;-) जोड़ा गया बोनस: आप अक्सर अपने कर्सर का चयन स्टेटमेंट फॉर लूप में एम्बेड कर सकते हैं: रिक इन (चयन ...) लूप – DCookie

0

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

गैर-समय loop भूल जाएं और exit भूल जाएं, यह आपको डबल निष्पादन से बचने के लिए करना चाहिए (आप टी-एसक्यूएल में भी बहुत कुछ करते हैं!)।

cursor c_mm is select a, b, c, d from mytable; 

    begin 
    open c_mm; 
    fetch c_mm into a, b, c, d; 
    while (not c_mm%notfound) loop 
     -- do what you have to do here 

     fetch c_mm into a, b, c, d; 
    end loop; 
    close c_mm; 
    end; 

कौन सा मैं वास्तव में समझ में नहीं आता क्यों सभी Oracle ज्ञान का आधार लेख और मंच पोस्ट (और stackoverflow) इस बाहर निकलने में एक पाश समाधान जो स्पष्ट रूप से गलत है को बढ़ावा देता है!

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