sql >> データベース >  >> RDS >> Oracle

関数パラメーターのカスタム遅延評価/短絡の構文

    遅延評価は、(部分的に)参照カーソル、条件付きコンパイルを使用して実装するか、即時実行することができます。 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;
    /
    



    1. チェックボックス(ブール値)の値をphpを使用してmysqlデータベースに保存する

    2. MySQLでカウンタをインクリメントして値を返す方法

    3. 特定の基準を満たす連続した日のグループを作成する

    4. MySqlエラーが一晩で発生します-サーバーに送信された最後のパケットは0ミリ秒前でした