自己記述型のオブジェクトが必要なようです。つまり、メタデータ ビューから選択することなく、変数の型をプログラムで見つけることができます。オブジェクトに聞いてみてください、あなたは何ですか?
ほとんどの場合、型はすでにわかっている (厳密に型指定されている) ため、ほとんどの状況では必要ないように思われます。たとえば、プロシージャのパラメータは通常、型 (数値、varchar2 など) を指定します。ローカル変数は通常、型を指定するか、%type 表記を介してデータベース オブジェクトの型に関連付けます。
任意のクエリに使用できる弱い型指定のカーソル変数など、弱い型指定のオブジェクトが必要または有用な状況がいくつかあります。過度に単純化した例:
create or replace procedure get_data(o_cur OUT SYS_REFCURSOR) as
begin
OPEN o_cur FOR
-- without changing parameter, this could select from any table
select * from emp;
end;
ここでの問題は、誰かがカーソルを別のテーブルで使用するようにコーディングすると、(実行時に) エラーが発生する可能性があることです (意図的にひどいプロシージャ名を選択しました)。何かのようなもの:
declare
l_cur sys_refcursor;
l_row dept%rowtype;
begin
get_data(l_cur);
-- oops, I thought this was dept data when I coded it, Oracle didn't complain at compile time
LOOP
fetch l_cur
into l_row;
exit when l_cur%notfound;
-- do something here
END LOOP;
close l_cur;
end;
これが、強く型付けされたカーソルを好み、この状況を避ける理由でもあります。
とにかく、自己記述型オブジェクトの場合は、SYS.ANYDATA 組み込み型を使用できます (同様に、ジェネリック コレクション型の SYS.ANYDATASET)。これは9iで導入されたと思います。たとえば、次のプロシージャは、いくつかのデータを取得し、タイプに基づいてロジックを分岐します。
CREATE OR REPLACE procedure doStuffBasedOnType(i_data in sys.anydata) is
l_type SYS.ANYTYPE;
l_typecode PLS_INTEGER;
begin
-- test type
l_typecode := i_data.GetType (l_type);
CASE l_typecode
when Dbms_Types.Typecode_NUMBER then
-- do something with number
dbms_output.put_line('You gave me a number');
when Dbms_Types.TYPECODE_DATE then
-- do something with date
dbms_output.put_line('You gave me a date');
when Dbms_Types.TYPECODE_VARCHAR2 then
-- do something with varchar2
dbms_output.put_line('You gave me a varchar2');
else
-- didn't code for this type...
dbms_output.put_line('wtf?');
end case;
end;
ここには、タイプに基づいたプログラムによる分岐があります。そしてそれを使用するには:
declare
l_data sys.anydata;
begin
l_data := sys.anydata.convertvarchar2('Heres a string');
doStuffBasedOnType(l_data);
end;
-- output: "You gave me a varchar2"
返信が長すぎなかったことを願っています;)