Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Eine Syntax für benutzerdefinierte verzögerte Auswertung/Kurzschluss von Funktionsparametern

Lazy Evaluation kann (teilweise) mit Ref-Cursorn, bedingter Kompilierung oder sofortiger Ausführung implementiert werden. Der ANYDATA-Typ kann verwendet werden, um generische Daten zu übergeben.

Referenz-Cursor

Ref-Cursor können mit einer statischen SQL-Anweisung geöffnet, als Argumente übergeben und erst ausgeführt werden, wenn sie benötigt werden.

Während dies Ihre Frage zur faulen Bewertung buchstäblich beantwortet, bin ich mir nicht sicher, ob es wirklich praktisch ist. Dies ist nicht die beabsichtigte Verwendung von Ref-Cursorn. Und es ist möglicherweise nicht bequem, SQL zu allem hinzufügen zu müssen.

Um zu beweisen, dass die langsame Funktion ausgeführt wird, erstellen Sie zunächst eine Funktion, die einfach für ein paar Sekunden schläft:

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;
/

Erstellen Sie eine Funktion, um festzustellen, ob eine Auswertung erforderlich ist:

create or replace function do_i_have_to_trace return boolean is
begin
    return true;
end;
/

Diese Funktion kann die Arbeit ausführen, indem sie die SQL-Anweisung ausführt. Die SQL-Anweisung muss etwas zurückgeben, auch wenn Sie keinen Rückgabewert wünschen.

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;
/

Erstellen Sie nun die Prozedur, die immer Trace aufruft, aber nicht unbedingt Zeit mit der Auswertung der Argumente verbringt.

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;
/

Standardmäßig erledigt es die Arbeit und ist langsam:

--Takes 2 seconds to run:
begin
    lazily_trace_something(2);
end;
/

Aber wenn Sie DO_I_HAVE_TO_TRACE ändern Um false zurückzugeben, ist die Prozedur schnell, obwohl sie ein langsames Argument übergibt.

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;
/

Andere Optionen

Die bedingte Kompilierung wird traditioneller verwendet, um die Instrumentierung zu aktivieren oder zu deaktivieren. Zum Beispiel:

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;
/

Vielleicht möchten Sie auch dynamisches SQL überdenken. Programmierstil und etwas syntaktischer Zucker können hier einen großen Unterschied machen. Kurz gesagt, die alternative Zitatsyntax und einfache Vorlagen können dynamisches SQL viel besser lesbar machen. Weitere Einzelheiten finden Sie in meinem Post hier .

Generische Daten weitergeben

Die ANY-Typen können verwendet werden, um jeden erdenklichen Datentyp zu speichern und zu übergeben. Leider gibt es keinen nativen Datentyp für jeden Zeilentyp. Sie müssen für jede Tabelle einen TYPE erstellen. Diese benutzerdefinierten Typen sind sehr einfach, sodass dieser Schritt bei Bedarf automatisiert werden kann.

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;
/