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