2011-07-15 12 views
20

以下の例では、pls_integerサブタイプごとに1つのto_str()関数と1つのset()プロシージャを書きました。関数とプロシージャは、型を除いてほぼ同じです。サブタイプの依存関係を解消するにはどうすればいいですか?

サブタイプによって提供されている制約を諦めることなく、新しいサブタイプの別のto_str()set()を書き込む必要性をどのように排除できますか?

procedure set(list in varchar2, prefix in varchar2) 

ようvarchar2にフォールバックして、あまりにも素晴らしいアイデアを鳴らない

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

として、それを呼び出すと、私はまだ各サブタイプのためto_str()を提供する必要があります。

私はOracleの初心者であり、新しいOracleの機能はほぼ毎日私を驚かせるので、私はさまざまな提案のためにオープンしています。

私は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

これまでの回答では、これはPL/SQLの痛みであり、おそらくサブタイプでは可能ではないと考えています。たぶん私はより大きなハンマーを使用する必要があります:[PL/SQL With Object Types](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があります。分析関数の方法はよく見えますが、私は11gでテストする必要はありません!

編集はそうでなければ、私はあなたがOracleのオブジェクトモデルを使用して探しているものを達成することができます考える;。。特に多型が、これはので、多分他の誰かがチャイムができます...私を超えている)

-1

以下の答えは、実際にpostgresql(とplpgsql)でどうやってやっているのか、そしてoracleサブタイプについてはわかりませんが、私はそれらが似ていると思っています。 。

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

私は構文が間違っていることは知っていますが、とにかくそれを表示する必要があります。

"anynonarray" or any of the alternativesを呼び出しのパラメータのタイプに置き換えるという考え方です。 1つの制限は、上記の例のすべての "anynonarray"がすべて同じタイプであることです。

ドキュメンテーションはこれを多型と呼びます。

関連する問題