sql >> Databasteknik >  >> RDS >> Oracle

En syntax för anpassad lat-utvärdering/kortslutning av funktionsparametrar

Lata utvärdering kan (delvis) implementeras med hjälp av ref-markörer, villkorlig kompilering eller köras omedelbart. ANYDATA-typen kan användas för att skicka generiska data.

Ref markör

Ref-markörer kan öppnas med en statisk SQL-sats, skickas som argument och kommer inte att köras förrän de behövs.

Även om detta bokstavligen svarar på din fråga om lat utvärdering, är jag inte säker på om det verkligen är praktiskt. Detta är inte den avsedda användningen av ref-markörer. Och det kanske inte är bekvämt att behöva lägga till SQL till allt.

Först, för att bevisa att den långsamma funktionen körs, skapa en funktion som helt enkelt sover i några sekunder:

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

Skapa en funktion för att avgöra om utvärdering är nödvändig:

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

Denna funktion kan utföra arbetet genom att köra SQL-satsen. SQL-satsen måste returnera något, även om du kanske inte vill ha ett returvärde.

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

Skapa nu proceduren som alltid kommer att anropa spårning men som inte nödvändigtvis lägger tid på att utvärdera argumenten.

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

Som standard gör den jobbet och är långsam:

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

Men när du ändrar DO_I_HAVE_TO_TRACE för att returnera falskt är proceduren snabb, även om den skickar ett långsamt argument.

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

Andra alternativ

Villkorlig kompilering används mer traditionellt för att aktivera eller inaktivera instrumentering. Till exempel:

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

Du kanske också vill ompröva dynamisk SQL. Programmeringsstil och lite syntaktisk socker kan göra stor skillnad här. Kort sagt, den alternativa citatsyntaxen och enkla mallar kan göra dynamisk SQL mycket mer läsbar. För mer information se mitt inlägg här .

Överför allmän data

Alla typer kan användas för att lagra och skicka alla tänkbara datatyper. Tyvärr finns det ingen inbyggd datatyp för varje radtyp. Du måste skapa en TYPE för varje tabell. Dessa anpassade typer är mycket enkla så att steget kan automatiseras vid behov.

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. När och hur man använder SQL PARTITION BY-satsen

  2. Mappning av sammansatta nycklar med EF-kod först

  3. Hur får jag ett Oracle SCHEMA som DDL-skript med DBMS_METADATA (och SCHEMA_EXPORT)

  4. postgresql date_trunc till godtycklig precision?