2012-04-19 18 views
7

मैं उपयोगकर्ता परिभाषित ऑब्जेक्ट से निपटने के लिए एक प्रक्रिया लिख ​​रहा हूं जो ANYDATA में संग्रहीत है। ऑब्जेक्ट प्रकार और विशेषता का नाम केवल रन टाइम पर ही जाना जा सकता है, इसलिए मैं घोषणा अनुभाग में इसके लिए viarable परिभाषित नहीं कर सकता। जावा में, मैं इसके साथ निपटने के लिए प्रतिबिंब का उपयोग कर सकता हूं, मैं कक्षा का नाम और फ़ील्ड नाम जान सकता हूं। फिर मैं प्रतिबिंब के माध्यम से खेतों तक पहुंच सकते हैं। क्या पीएलएसक्यूएल में ऐसा करने का कोई तरीका है? मेरे सिर में अभी क्या प्रक्रिया में गतिशील रूप से एक एसक्यूएल स्ट्रिंग बना रहा है और इसे निष्पादित कर रहा है। लेकिन यह वही नहीं है जो मैं चाहता हूं।प्रतिबिंब?

मान लें कि, उपयोगकर्ता ए ने एडीटी प्रकार को create or replace type Person_type as object (fname varchar2(10), lname varchar2(10)); के रूप में परिभाषित किया है और ऑब्जेक्ट इंस्टेंस बनाया है और इसे ANYDATA में डाला है।

मेरी प्रक्रिया में, किसी भी तरह से मुझे पता है कि मुझे इस ऑब्जेक्ट की पहली विशेषता से निपटने की आवश्यकता है, जो कि fname है। तो अगर पहले स्थान पर एडीटी प्रकार पता है, मेरे कोड किया जाएगा:

declare 
    adobject A.Person_type; -- HERE! I don't know the type yet, so I can't define adobject! 
    tempAnydata anydata; 
    rt number; 
    vbuffer varchar2(10); 
    ... 
begin 
    select somecolumn 
    into tempAnydata 
    from sometable 
    where something='something' for update; 

    rt := tempAnydata.GetObject(adobject); 

    vbuffer := adobject.fname; -- HERE! I don't know the attribute name is fname! 
    -- deal with vbuffer here 
end; 

तो क्या मैं यह गतिशील बनाने के लिए क्या करना चाहिए? अग्रिम में धन्यवाद।

+0

आप जानते हैं कि 'tempAnydata' है * वास्तव में * एक' A.person_type' के रूप में आप निश्चित रूप से करते हैं (अन्यथा आप 'GetObject (adobject नहीं कर सका)' वास्तव में इस प्रकार के adobject के साथ) तो आप * यह भी जानते हैं कि उस प्रकार की पहली विशेषता क्या है। या क्या मैं कुछ न कुछ भूल रहा हूं? –

+0

A.person_type सिर्फ एक उदाहरण है, यह किसी भी उपयोगकर्ता परिभाषित प्रकार हो सकता है। यह banymal_type या कुछ और हो सकता है। – icespace

+1

स्टेटिक मजबूत टाइपिंग बेकार है। (गड़बड़ पुराने स्मॉलटाकर बंद हो जाता है, स्वयं को विचलित कर देता है :-) –

उत्तर

7

ANYDATA का वर्णन करने के लिए आपको ANYTYPE का उपयोग करने की आवश्यकता है और यह सुनिश्चित करें कि प्रकार सही है। फिर आप piecewise और getVarchar2 का उपयोग करके विशेषता का उपयोग कर सकते हैं।

नीचे दिया गया अधिकांश कोड उस प्रकार की जांच के लिए है, जिसकी आपको आवश्यकता नहीं है यदि आप प्रकार की सुरक्षा के बारे में चिंतित नहीं हैं।

create or replace function get_first_attribute(
    p_anydata in out anydata --note the "out" - this is required for the "piecewise" 
) return varchar2 is 
    v_typecode pls_integer; 
    v_anytype anytype; 
begin 
    --Get the typecode, and the ANYTYPE 
    v_typecode := p_anydata.getType(v_anytype); 

    --Check that it's really an object 
    if v_typecode = dbms_types.typecode_object then 
     --If it is an object, find the first item 
     declare 
      v_first_attribute_typecode pls_integer; 
      v_aname   varchar2(32767); 
      v_result   pls_integer; 
      v_varchar  varchar2(32767); 
      --Variables we don't really care about, but need for function output 
      v_prec   pls_integer; 
      v_scale   pls_integer; 
      v_len   pls_integer; 
      v_csid   pls_integer; 
      v_csfrm   pls_integer; 
      v_attr_elt_type anytype; 
     begin 
      v_first_attribute_typecode := v_anytype.getAttrElemInfo(
       pos   => 1, --First attribute 
       prec   => v_prec, 
       scale   => v_scale, 
       len   => v_len, 
       csid   => v_csid, 
       csfrm   => v_csfrm, 
       attr_elt_type => v_attr_elt_type, 
       aname   => v_aname); 

      --Check typecode of attribute 
      if v_first_attribute_typecode = dbms_types.typecode_varchar2 then 
       --Now that we've verified the type, get the actual value. 
       p_anydata.piecewise; 
       v_result := p_anydata.getVarchar2(c => v_varchar); 

       --DEBUG: Print the attribute name, in case you're curious 
       --dbms_output.put_line('v_aname: '||v_aname); 

       return v_varchar; 
      else 
       raise_application_error(-20000, 'Unexpected 1st Attribute Typecode: '|| 
        v_first_attribute_typecode); 
      end if; 
     end; 
    else 
     raise_application_error(-20000, 'Unexpected Typecode: '||v_typecode); 
    end if; 
end; 
/

प्रकार::

create or replace type Person_type as object (fname varchar2(10), lname varchar2(10)); 

create or replace type other_type as object (first_name varchar2(10), poetry clob); 

टेस्ट रन:

declare 
    --Create records 
    v_type1 person_type := person_type('Ford', 'Prefect'); 
    v_type2 other_type := other_type('Paula', 'blah blah...'); 
    v_anydata anydata; 
begin 
    --Convert to ANYDATA. 
    --Works as long as ANYDATA is an object with a varchar2 as the first attribute. 
    v_anydata := anydata.convertObject(v_type1); 
    dbms_output.put_line(get_first_attribute(v_anydata)); 

    v_anydata := anydata.convertObject(v_type2); 
    dbms_output.put_line(get_first_attribute(v_anydata)); 
end; 
/

आउटपुट

समारोह मान देने के लिए :

Ford 
Paula 
+0

+1 - मैं अपना जवाब हटा दूंगा। मुझे अभी भी लगता है कि ओपी का आर्किटेक्चर एक असाधारण है, लेकिन अगर वे वास्तव में लुमेन हैं तो यह सही समाधान है – APC

+0

@ एएपीसी मुझे लगता है कि आपको अपना जवाब रखना चाहिए, यह सहायक हो सकता है। मैंने एनाडाटा की तुलना में ऑब्जेक्ट-रिलेशनल समाधानों को अक्सर देखा है। (हालांकि सामान्य रूप से मैं उन दोनों से बचने की कोशिश करता हूं; मैं हमेशा अत्यधिक सामान्य समाधानों पर थोड़ा सा संदेह करता हूं।) –

+0

कमाल! बहुत बहुत धन्यवाद, जोनियर। यह वास्तव में मैं चाहता हूँ! ANYTYPE, आपसे मिलकर अच्छा लगा। – icespace