9

ANYDATA に格納されているユーザー定義オブジェクトを処理する手順を作成しています。オブジェクトの型と属性名は実行時にしか分からないため、declare セクションで viarable を定義できません。Javaでは、リフレクションを使用して対処できます。クラス名とフィールド名を知ることができます。次に、リフレクションを介してフィールドにアクセスできます。そのようにPLSQLでそれを行う方法はありますか? 私の頭の中では、プロシージャで動的にSQL文字列を作成して実行しています。しかし、それは私が正確に望んでいるものではありません。

ユーザー A が ADT 型を定義しcreate or replace type Person_type as object (fname varchar2(10), lname varchar2(10));、オブジェクト インスタンスを作成して ANYDATA に挿入するとします。

私の手順では、このオブジェクトの最初の属性である fname を処理する必要があることがどういうわけかわかっています。したがって、最初に adt タイプを知っている場合、私のコードは次のようになります。

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;

では、動的にするにはどうすればよいですか? 前もって感謝します。

4

1 に答える 1

7

を使用ANYTYPEして記述しANYDATA、タイプが正しいことを確認する必要があります。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
于 2012-04-20T04:13:38.533 に答える