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

En syntaks til tilpasset doven-evaluering/kortslutning af funktionsparametre

Doven evaluering kan (delvist) implementeres ved hjælp af ref-markører, betinget kompilering eller udføres med det samme. ANYDATA-typen kan bruges til at videregive generiske data.

Ref markør

Ref-markører kan åbnes med en statisk SQL-sætning, sendes som argumenter og vil ikke udføres, før de er nødvendige.

Selvom dette bogstaveligt talt besvarer dit spørgsmål om doven evaluering, er jeg ikke sikker på, om det virkelig er praktisk. Dette er ikke den tilsigtede brug af ref markører. Og det er måske ikke praktisk at skulle tilføje SQL til alting.

Først, for at bevise, at den langsomme funktion kører, skal du oprette en funktion, der simpelthen sover i et par 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;
/

Opret en funktion for at bestemme, om evaluering er nødvendig:

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

Denne funktion kan udføre arbejdet ved at udføre SQL-sætningen. SQL-sætningen skal returnere noget, selvom du måske ikke ønsker en returværdi.

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

Opret nu proceduren, der altid vil kalde sporing, men som ikke nødvendigvis vil bruge tid på at evaluere argumenterne.

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 udfører den arbejdet og er langsom:

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

Men når du ændrer DO_I_HAVE_TO_TRACE for at returnere falsk er proceduren hurtig, selvom den sender et langsomt 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;
/

Andre muligheder

Betinget kompilering bruges mere traditionelt til at aktivere eller deaktivere instrumentering. For eksempel:

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

Det kan også være en god idé at genoverveje dynamisk SQL. Programmeringsstil og noget syntaktisk sukker kan gøre en stor forskel her. Kort sagt kan den alternative citatsyntaks og simple skabeloner gøre dynamisk SQL meget mere læsbar. For flere detaljer se mit indlæg her .

Videregivelse af generiske data

Alle typer kan bruges til at gemme og videregive enhver tænkelig datatype. Desværre er der ingen indbygget datatype for hver rækketype. Du skal oprette en TYPE for hver tabel. Disse brugerdefinerede typer er meget enkle, så det trin kan automatiseres, hvis det er nødvendigt.

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. Hvordan tæller man på hinanden følgende dubletter i en tabel?

  2. tilføje manglende dato i en tabel i PostgreSQL

  3. Sådan opretter og sletter du databaser og tabeller i MySQL

  4. Docker Compose + Postgres:Udsæt port