2011-07-15 18 views
20

नीचे दिए गए उदाहरण में मैंने प्रत्येक सबटाइप के लिए एक to_str() फ़ंक्शन और एक set() प्रक्रिया लिखा है। कार्य और प्रक्रियाएं प्रकार को छोड़कर लगभग समान हैं।उप प्रकार निर्भरता को कैसे खत्म करें?

मैं कैसे उप प्रकार द्वारा प्रदान की बाधा को देने के बिना अभी तक एक और to_str() और set() एक नया उप-प्रकार के लिए लिखने के लिए की आवश्यकता को समाप्त कर सकते हैं?

तरह

procedure set(list in varchar2, prefix in varchar2) 

varchar2 पर वापस गिरने और फिर

set(to_str(list), 'foos:') 

यह बुला भी बहुत अच्छा विचार नहीं लग रहा है और मैं अभी भी एक उप-प्रकार के लिए to_str() प्रदान करने के लिए की जरूरत है।

मैं सभी प्रकार के विभिन्न प्रस्तावों के लिए खुला हूं क्योंकि मैं ओरेकल नौसिखिया हूं और नई ओरेकल सुविधाओं में मुझे लगभग दैनिक लगता है।

मैं 11.2.0.1.0 चला रहा हूं।

create table so1table (
    id number, 
    data varchar(20) 
); 

create or replace package so1 as 
    subtype foo_t is pls_integer range 0 .. 4 not null; 
    type foolist is table of foo_t; 
    procedure set(id_ in number, list in foolist default foolist(1)); 

    subtype bar_t is pls_integer range 5 .. 10 not null; 
    type barlist is table of bar_t; 
    procedure set(id_ in number, list in barlist default barlist(5)); 
end; 
/
show errors 

create or replace package body so1 as 
    /* Do I have always to implement these very similar functions/procedures for 
    every single type ? */ 
    function to_str(list in foolist) return varchar2 as 
    str varchar2(32767); 
    begin 
    for i in list.first .. list.last loop 
     str := str || ' ' || list(i); 
    end loop; 
    return str; 
    end; 

    function to_str(list in barlist) return varchar2 as 
    str varchar2(32767); 
    begin 
    for i in list.first .. list.last loop 
     str := str || ' ' || list(i); 
    end loop; 
    return str; 
    end; 

    procedure set(id_ in number, list in foolist default foolist(1)) as 
    values_ constant varchar2(32767) := 'foos:' || to_str(list); 
    begin 
    insert into so1table (id, data) values (id_, values_); 
    end; 

    procedure set(id_ in number, list in barlist default barlist(5)) as 
    values_ constant varchar2(32767) := 'bars:' || to_str(list); 
    begin 
    insert into so1table (id, data) values (id_, values_); 
    end; 
end; 
/
show errors 

begin 
    so1.set(1, so1.foolist(0, 3)); 
    so1.set(2, so1.barlist(5, 7, 10)); 
end; 
/

SQLPLUS> select * from so1table; 

     ID DATA 
---------- -------------------- 
     1 foos: 0 3 
     2 bars: 5 7 10 
+0

प्रतिक्रिया के आधार पर (18 अप-वोट, 4 पसंदीदा और दो सटीक उत्तर नहीं) अब तक मुझे लगता है कि यह एक पीएल/एसक्यूएल का दर्द बिंदु है और शायद उपप्रकारों के साथ संभव नहीं है। शायद मुझे एक बड़ा हथौड़ा का उपयोग करना होगा: [ऑब्जेक्ट प्रकारों के साथ पीएल/एसक्यूएल का उपयोग करना] (http://download.oracle.com/docs/cd/E11882_01/appdev.112/e11822/adobjplsql.htm)? – user272735

उत्तर

3
create table so1table (
    id number, 
    data varchar(20) 
); 


create or replace type parent_type as object 
(
    v_number number, 
    --Prefix probably belongs with a list, not an individual value. 
    --For simplicity, I'm not adding another level to the objects. 
    v_prefix varchar2(10) 
) not instantiable not final; 
/

create or replace type parentlist as table of parent_type; 
/


create or replace type foo_type under parent_type 
(
    constructor function foo_type(v_number number) return self as result 
); 
/

--The data must be stored as a NUMBER, since ADTs don't support 
--PL/SQL specific data types. The type safety is enforced by the 
--conversion in the constructor. 
create or replace type body foo_type is 
    constructor function foo_type(v_number number) return self as result 
    as 
     subtype foo_subtype is pls_integer range 0 .. 4 not null; 
     new_number foo_subtype := v_number; 
    begin 
     self.v_number := new_number; 
     self.v_prefix := 'foos:'; 
     return; 
    end; 
end; 
/

create or replace type foolist as table of foo_type; 
/


create or replace type bar_type under parent_type 
(
    constructor function bar_type(v_number number) return self as result 
); 
/

create or replace type body bar_type is 
    constructor function bar_type(v_number number) return self as result 
    as 
     subtype bar_subtype is pls_integer range 5 .. 10 not null; 
     new_number bar_subtype := v_number; 
    begin 
     self.v_number := new_number; 
     self.v_prefix := 'bars:'; 
     return; 
    end; 
end; 
/

create or replace type barlist as table of bar_type; 
/



create or replace package so1 as 
    procedure set(id_ in number, list in parentlist); 
end; 
/

create or replace package body so1 as 

    function to_str(list in parentlist) return varchar2 as 
     v_value VARCHAR2(32767); 
    begin 
     for i in list.first .. list.last loop 
      if i = 1 then 
       v_value := list(i).v_prefix; 
      end if; 
      v_value := v_value || ' ' || list(i).v_number; 
     end loop; 

     return v_value; 
    end to_str; 

    procedure set(id_ in number, list in parentlist) as 
     values_ constant varchar2(32767) := to_str(list); 
    begin 
     insert into so1table (id, data) values (id_, values_); 
    end set; 
end so1; 
/


begin 
    --You probably don't want to mix foos and bars, but it is allowed. 
    so1.set(1, parentlist(foo_type(0), foo_type(3))); 
    so1.set(2, parentlist(bar_type(5), bar_type(7), bar_type(10))); 

    --These would generate "ORA-06502: PL/SQL: numeric or value error" 
    --so1.set(1, parentlist(foo_type(5))); 
    --so1.set(1, parentlist(bar_type(4))); 

end; 
/

select * from so1table; 
+0

अंततः एक उत्तर जो समझ में आता है। धन्यवाद !फिलहाल मुझे यह पसंद नहीं है कि उन सभी ऑब्जेक्ट प्रकारों को पैकेज के अंदर छुपाया नहीं जा सकता है, लेकिन उपयोगकर्ता के नामस्थान को प्रदूषित कर सकते हैं। मुझे लगता है कि ओरेकल के साथ रास्ता है। – user272735

1

यह अपना उत्तर मिल सकता है, लेकिन क्यों नहीं एक नियमित रूप से तालिका में डेटा शब्दों में कहें, तो श्रेणीबद्ध उन्हें, जैसा कि आप दिखाने के लिए, wm_concat एकत्रीकरण समारोह का उपयोग कर?

अर्थात,

> select * from myTable; 

ID Category Value 
--- --------- ------ 
1 foo  0 
2 foo  3 
3 bar  5 
4 bar  7 
5 bar  10 

> select Category||'s: '||replace(wm_concat(Value),',',' ') Data 
    from  myTable 
    group by Category; 

Data 
------------- 
bars: 5 7 10 
foos: 0 3 

wm_concat स्वतंत्र टाइप है, इसलिए कोई जरूरत नहीं है कि आप अपने कार्यों ओवरलोड के लिए नहीं है। इसके अलावा, अन्य methods हैं जिनका उपयोग किया जा सकता है; विश्लेषणात्मक फ़ंक्शन विधि अच्छी लगती है, लेकिन मेरे पास परीक्षण करने के लिए 11 जी नहीं है!

(संपादित अन्यथा, मुझे लगता है कि आप प्राप्त कर सकते हैं आप Oracle की ऑब्जेक्ट मॉडल का उपयोग कर के लिए क्या देख रहे;। विशेष रूप से बहुरूपता बहरहाल, यह मुझे बाहर है ... इसलिए शायद किसी और में झंकार कर सकते हैं।)

-1

निम्नलिखित उत्तर वास्तव में पोस्टग्रेस्क्ल (और plpgsql) में आप इसे कैसे करेंगे, और मुझे ऑरैकल उपप्रकारों के बारे में भी पता नहीं है, लेकिन मुझे लगता है कि वे इतने समान हैं कि कम से कम यह आपको आपके उत्तर में ले जाएगा ।

create function add (anynonarray,anynonarray) returning anynonarray 
as 'begin return $1 + $2; end'; 

मुझे पता है कि मैंने वाक्यविन्यास को टक्कर लगी है, लेकिन यह दिखाना चाहिए कि मैं इसके साथ क्या दिखाना चाहता हूं, वैसे भी।

विचार यह है कि यह कॉल के पैरामीटर के प्रकार के साथ "anynonarray" or any of the alternatives को प्रतिस्थापित करेगा। एक प्रतिबंध यह है कि ऊपर दिए गए उदाहरण में सभी "anynonarray" एक ही प्रकार के होंगे।

प्रलेखन इसे बहुरूपता के रूप में संदर्भित करता है।