sql >> Database >  >> RDS >> Oracle

Een syntaxis voor aangepaste luie-evaluatie/kortsluiting van functieparameters

Luie evaluatie kan (gedeeltelijk) worden geïmplementeerd met behulp van ref-cursors, voorwaardelijke compilatie of onmiddellijk worden uitgevoerd. Het type ANYDATA kan worden gebruikt om generieke gegevens door te geven.

Ref-cursor

Ref-cursors kunnen worden geopend met een statische SQL-instructie, worden doorgegeven als argumenten en worden pas uitgevoerd als ze nodig zijn.

Hoewel dit letterlijk je vraag over luie evaluatie beantwoordt, weet ik niet zeker of het echt praktisch is. Dit is niet het beoogde gebruik van ref-cursors. En het is misschien niet handig om overal SQL aan toe te voegen.

Om te bewijzen dat de langzame functie actief is, moet u eerst een functie maken die een paar seconden slaapt:

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

Maak een functie om te bepalen of evaluatie nodig is:

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

Deze functie kan het werk uitvoeren door de SQL-instructie uit te voeren. De SQL-instructie moet iets teruggeven, ook al wil je misschien geen retourwaarde.

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

Maak nu de procedure die altijd tracering aanroept, maar die niet noodzakelijkerwijs tijd zal besteden aan het evalueren van de 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;
/

Standaard doet het het werk en is het traag:

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

Maar wanneer u DO_I_HAVE_TO_TRACE . wijzigt om false terug te geven is de procedure snel, ook al geeft het een langzaam argument door.

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 opties

Voorwaardelijke compilatie wordt traditioneel gebruikt om instrumentatie in of uit te schakelen. Bijvoorbeeld:

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

U kunt ook dynamische SQL opnieuw overwegen. Programmeerstijl en wat syntactische suiker kunnen hier een groot verschil maken. Kortom, de alternatieve syntaxis van aanhalingstekens en eenvoudige sjablonen kunnen dynamische SQL veel leesbaarder maken. Voor meer details zie mijn post hier .

Generieke gegevens doorgeven

De ANY-typen kunnen worden gebruikt om elk denkbaar gegevenstype op te slaan en door te geven. Helaas is er geen systeemeigen gegevenstype voor elk rijtype. U moet voor elke tabel een TYPE maken. Die aangepaste typen zijn heel eenvoudig, zodat die stap indien nodig kan worden geautomatiseerd.

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. Moet de namen van werknemers ordenen volgens de kolom van hun stad

  2. SQL:hoe vul ik lege cellen met de vorige rijwaarde?

  3. Spring JPA met behulp van specificaties en criteriaQuery op gezamenlijke tabellen

  4. SQLite-queryresultaten opmaken als een door komma's gescheiden lijst