Oracle
 sql >> Database >  >> RDS >> Oracle

Una sintassi per la valutazione pigra personalizzata/il cortocircuito dei parametri di funzione

La valutazione pigra può essere (parzialmente) implementata utilizzando i cursori di riferimento, la compilazione condizionale o l'esecuzione immediata. Il tipo ANYDATA può essere utilizzato per passare dati generici.

Rif Cursore

I cursori di riferimento possono essere aperti con un'istruzione SQL statica, passati come argomenti e non verranno eseguiti fino a quando non sarà necessario.

Anche se questo risponde letteralmente alla tua domanda sulla valutazione pigra, non sono sicuro che sia veramente pratico. Questo non è l'uso previsto dei cursori di riferimento. E potrebbe non essere conveniente dover aggiungere SQL a tutto.

Innanzitutto, per dimostrare che la funzione lenta è in esecuzione, crea una funzione che si fermi per alcuni secondi:

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

Crea una funzione per determinare se è necessaria la valutazione:

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

Questa funzione può eseguire il lavoro eseguendo l'istruzione SQL. L'istruzione SQL deve restituire qualcosa, anche se potresti non volere un valore restituito.

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

Ora crea la procedura che chiamerà sempre trace ma non impiegherà necessariamente tempo a valutare gli argomenti.

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

Per impostazione predefinita sta facendo il lavoro ed è lento:

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

Ma quando cambi DO_I_HAVE_TO_TRACE per restituire false la procedura è veloce, anche se sta passando un argomento lento.

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

Altre opzioni

La compilazione condizionale è più tradizionalmente utilizzata per abilitare o disabilitare la strumentazione. Ad esempio:

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

Potresti anche voler riconsiderare l'SQL dinamico. Lo stile di programmazione e un po' di zucchero sintattico possono fare una grande differenza qui. In breve, la sintassi delle virgolette alternative e i modelli semplici possono rendere l'SQL dinamico molto più leggibile. Per maggiori dettagli, vedere il mio post qui .

Trasmissione di dati generici

I tipi QUALSIASI possono essere utilizzati per archiviare e trasmettere qualsiasi tipo di dati immaginabile. Sfortunatamente non esiste un tipo di dati nativo per ogni tipo di riga. Dovrai creare un TIPO per ogni tabella. Questi tipi personalizzati sono molto semplici in modo che il passaggio possa essere automatizzato se necessario.

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