Мързеливата оценка може да бъде (частично) реализирана с помощта на референтни курсори, условна компилация или незабавно изпълнение. Типът 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;
/