遅延評価は、(部分的に)参照カーソル、条件付きコンパイルを使用して実装するか、即時実行することができます。 ANYDATAタイプは、汎用データを渡すために使用できます。
参照カーソル
参照カーソルは静的SQLステートメントで開くことができ、引数として渡され、必要になるまで実行されません。
これは文字通り遅延評価に関するあなたの質問に答えますが、それが本当に実用的かどうかはわかりません。これは、参照カーソルの使用目的ではありません。そして、すべてにSQLを追加しなければならないのは便利ではないかもしれません。
まず、遅い関数が実行されていることを証明するために、数秒間スリープするだけの関数を作成します。
grant execute on sys.dbms_lock to <your_user>;
create or replace function sleep(seconds number) return number is
begin
dbms_lock.sleep(seconds);
return 1;
end;
/
評価が必要かどうかを判断する関数を作成します。
create or replace function do_i_have_to_trace return boolean is
begin
return true;
end;
/
この関数は、SQLステートメントを実行することによって作業を実行できます。戻り値が必要ない場合でも、SQLステートメントは何かを返す必要があります。
create or replace procedure trace_something(p_cursor sys_refcursor) is
v_dummy varchar2(1);
begin
if do_i_have_to_trace then
fetch p_cursor into v_dummy;
end if;
end;
/
次に、常にトレースを呼び出すが、必ずしも引数の評価に時間を費やすとは限らないプロシージャを作成します。
create or replace procedure lazily_trace_something(some_number in number) is
v_cursor sys_refcursor;
begin
open v_cursor for select sleep(some_number) from dual;
trace_something(v_cursor);
end;
/
デフォルトでは、それは仕事をしていて遅いです:
--Takes 2 seconds to run:
begin
lazily_trace_something(2);
end;
/
ただし、DO_I_HAVE_TO_TRACE
を変更すると falseを返すには、遅い引数を渡しても、プロシージャは高速です。
create or replace function do_i_have_to_trace return boolean is
begin
return false;
end;
/
--Runs in 0 seconds.
begin
lazily_trace_something(2);
end;
/
その他のオプション
条件付きコンパイルは、インストルメンテーションを有効または無効にするために、より伝統的に使用されます。例:
create or replace package constants is
c_is_trace_enabled constant boolean := false;
end;
/
declare
v_dummy number;
begin
$if constants.c_is_trace_enabled $then
v_dummy := sleep(1);
This line of code does not even need to be valid!
(Until you change the constant anyway)
$else
null;
$end
end;
/
動的SQLを再検討することもできます。プログラミングスタイルといくつかのシンタックスシュガーは、ここで大きな違いを生む可能性があります。つまり、代替の引用構文と単純なテンプレートにより、動的SQLがはるかに読みやすくなります。詳細については、私の投稿こちら> 。
一般的なデータの受け渡し
ANYタイプは、考えられる任意のデータタイプを格納および渡すために使用できます。残念ながら、各行タイプにネイティブデータ型はありません。テーブルごとにTYPEを作成する必要があります。これらのカスタムタイプは非常に単純なので、必要に応じて手順を自動化できます。
create table some_table(a number, b number);
create or replace type some_table_type is object(a number, b number);
declare
a_rowtype_variable some_table_type;
v_anydata anydata;
v_cursor sys_refcursor;
begin
a_rowtype_variable := some_table_type(1,2);
v_anydata := anydata.ConvertObject(a_rowtype_variable);
open v_cursor for select v_anydata from dual;
trace_something(v_cursor);
end;
/