2009-11-13 12 views
7

यह उन लोगों में से एक है "प्रश्नों को बेहतर तरीके से होना चाहिए" प्रश्न। मुझे समस्या स्थापित करने दो, तो मैं आपको अपना हैकड समाधान दूंगा, और शायद आप एक बेहतर समाधान का सुझाव दे सकते हैं। धन्यवाद!पीएल/एसक्यूएल में एक एसोसिएटिव सरणी को रीसेट करना?

चलें पी एल के इस छोटे से tidbit ले/एसक्यूएल

DECLARE 
TYPE foo_record IS RECORD (foo%type, bar%type); 
TYPE foo_records IS TABLE OF foo_record INDEX BY PLS_INTEGER; 
arr_foos foo_records; 

CURSOR monkeys is SELECT primates FROM zoo; 
row_monkey monkeys%rowtype; 
BEGIN 
FOR row_monkey IN monkeys loop 
    /* 
    at this point in each iteration I need to have the associative array 
    arr_foos in its original state. if this were java, I'd declare it 
    right here and its scope would be limited to this iteration. However, 
    this is not java, so the scope of the array is effectively global and 
    I can't have one iteration's data meddle with the next. 
    */ 
    null; 
END LOOP; 
END; 

कि मतलब है? मुझे मूल रूप से इसे किसी चीज़ पर रीसेट करने की आवश्यकता है। यदि यह एक संख्या थी जो शून्य से शुरू होती है, तो मैं केवल संख्या कह सकता हूं: = 0; प्रत्येक पुनरावृत्ति के शीर्ष पर और इसके साथ किया जाना चाहिए। लेकिन यह एक संख्या नहीं है, यह एक प्रकार है जिसे मैं सिर्फ एक साफ के साथ रीसेट कर सकता हूं: = 0।

वैसे भी, मेरी हैक पर:

DECLARE 
TYPE foo_record IS RECORD (foo%type, bar%type); 
TYPE foo_records IS TABLE OF foo_record INDEX BY PLS_INTEGER; 
arr_foos foo_records; 
arr_foos_reset foo_records; 

CURSOR monkeys is SELECT primates FROM zoo; 
row_monkey monkeys%rowtype; 
BEGIN 
FOR row_monkey IN monkeys loop 
    arr_foos := arr_foos_reset; 
    null; 
END LOOP; 
END; 

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

टैंक!

+1

माइनर nitpick: आप 'row_monkey बंदरों घोषित करने के लिए% rowtype जरूरत नहीं है,'। इस तरह की लूप के लिए एक कर्सर आपके लिए घोषणा करता है और लूप बॉडी तक सीमित है। इस कोड में, चर दो बार घोषित किया जाता है, और आंतरिक संस्करण बाहरी को छाया देता है। हालांकि यह कोई समस्या नहीं है - बस सोचा कि मैं इसे किसी और के पढ़ने के लिए जोड़ दूंगा। – AdamRossWalker

उत्तर

18

सबसे आसान तरीका:

arr_foos.Delete(); 

अन्य तरीका FOR पाश अंदर चर घोषित करने के लिए है। इस तरह से प्रत्येक पास के लिए इसे फिर से बनाया जाएगा।

DECLARE 
TYPE foo_record IS RECORD (foo%type, bar%type); 
TYPE foo_records IS TABLE OF foo_record INDEX BY PLS_INTEGER;  

CURSOR monkeys is SELECT primates FROM zoo; 
row_monkey monkeys%rowtype; 
BEGIN 
FOR row_monkey IN monkeys loop 
    DECLARE 
    arr_foos foo_records; 
    BEGIN 
    null; 
    END; 
END LOOP; 
END; 
+2

धन्यवाद! मुझे एहसास नहीं हुआ कि आप BEGIN के बाद DECLARE कह सकते हैं। (: – steve

+2

आप किसी भी समय घोंसला कर सकते हैं। इस तरह आप कोड के छोटे ब्लॉक (जैसे सी # या जावा में कोशिश/पकड़) में अपवाद भी प्राप्त कर सकते हैं। मेरी राय में बहुत उपयोगी सुविधा। – Majkel

1

आप एक संग्रह में चिड़ियाघर तालिका से डेटा पढ़ने जा रहे हैं:

इस तरह

? तो फिर वहाँ एक बेहतर तरीका है:

DECLARE 
    type foos_ts is table of zoo.foo%type index by pls_integer; 
    foos foos_t; 
BEGIN 
    select foo 
    bulk collect into foos 
    from zoo; 
    ... 
END; 

थोक एकत्रित करने में प्राप्त करने में कठिनाई से पहले संग्रह को साफ करता है, और यह पाश में पंक्ति-दर-पंक्ति पढ़ने में तो तेजी से काम करता है। दुर्भाग्य से, यह रिकॉर्ड के साथ काम नहीं करता है, इसलिए आपको प्रत्येक फ़ील्ड के लिए कई पीएल/एसक्यूएल टेबल की आवश्यकता होगी।

आप यहाँ अतिरिक्त जानकारी प्राप्त कर सकते हैं: Retrieving Query Results into Collections with the BULK COLLECT Clause

+0

अच्छी टिप, धन्यवाद – steve

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