数値IDフィールドとXMLTypeフィールドの同じフィールドを持つ行をすべて返すカーソルがたくさんあります。これらのカーソルの1つにアクセスするたびに(各カーソルにはアクセス用の独自の関数があります)、同じパターンを実行します。
--query behind cursor is designed to no more than one row.
for rec in c_someCursor(in_searchKey => local_search_key_value) loop
v_id := rec.ID
v_someXMLVar := rec.XMLDataField
end loop;
if v_someXMLVar is null then
/* A bunch of mostly-standard error handling and logging goes here */
end if;
exception
/* all cursor access functions have the same error-handling */
end;
パターンがより明白になるにつれて、それを単一の機能に集中させることが理にかなっています。
function fn_standardCursorAccess(in_cursor in t_xmlCursorType, in_alt in XMLType) return XMLType is
v_XMLData XMLType;
begin
dbms_application_info.set_module(module_name => $$PLSQL_UNIT, action_name => 'fn_standardCursorAccess');
loop
fetch in_cursor
into v_XMLData;
exit when in_cursor%notfound;
end loop;
/*some additional standard processing goes here*/
return v_XML;
exception
/*standard exception handling happens here*/
end;
私が遭遇した問題は、この関数を呼び出すことです。私は今それをこのように呼ぶ必要があります:
open v_curs for select /*blah blah blah*/ where key_field = x and /*...*/;
v_data := fn_standardCursorAccess(v_curs,alt);
close v_curs;
私がやりたいのは、次のように呼ぶことです。
open v_curs for c_getSomeData(x);
v_data := fn_standardCursorAccess(v_curs,alt);
close v_curs;
...コードへの変更の量を最小限に抑えるためです(これらのカーソルをすべて、それらに依存する関数にカットアンドペーストする必要はありません。複数の関数が同じカーソルに依存している場合は、これを新しい関数でラップする必要があります)。
残念ながら、これは機能しません。Oracleは次のようなエラーを返します。
Error: PLS-00222: no function with name 'C_GETSOMEDATA' exists in this scope
私がやろうとしていることは可能ですか?
(Oracleバージョンは10.2です)
編集: 私がしていることを説明するためのより良い方法は、明示的なカーソルへの参照を、カーソルによって返されるデータに対していくつかの一般的なルーチンを実行する関数に渡すことだと思います。明示カーソルでopen-forステートメントを使用できないようですが、明示カーソルへの参照を取得して、その参照を関数に渡すことができる他の方法はありますか?たぶん私がこの問題に取り組むことができる他の方法がありますか?
編集: R Van Rijnの返信に対する私の以前の返信からのコピーと貼り付け:
パッケージ仕様でカーソルを宣言し、パッケージ名で参照してみました:open v_curs for PKG.c_getSomeData(x); ...これにより、PKG.c_getSomeDataは関数または配列である必要があるという新しいエラーが発生します。そのように使用されます。
更新: 私はここでDBAに話しました、彼はrefカーソルが明示カーソルを指すようにすることは不可能であると言います。結局、これはできないようです。残念。:(