La respuesta para Oracle depende. Se llamará a la función para cada fila seleccionada A MENOS que la Función esté marcada como "Determinística", en cuyo caso solo se llamará una vez.
CREATE OR REPLACE PACKAGE TestCallCount AS
FUNCTION StringLen(SrcStr VARCHAR) RETURN INTEGER;
FUNCTION StringLen2(SrcStr VARCHAR) RETURN INTEGER DETERMINISTIC;
FUNCTION GetCallCount RETURN INTEGER;
FUNCTION GetCallCount2 RETURN INTEGER;
END TestCallCount;
CREATE OR REPLACE PACKAGE BODY TestCallCount AS
TotalFunctionCalls INTEGER := 0;
TotalFunctionCalls2 INTEGER := 0;
FUNCTION StringLen(SrcStr VARCHAR) RETURN INTEGER AS
BEGIN
TotalFunctionCalls := TotalFunctionCalls + 1;
RETURN Length(SrcStr);
END;
FUNCTION GetCallCount RETURN INTEGER AS
BEGIN
RETURN TotalFunctionCalls;
END;
FUNCTION StringLen2(SrcStr VARCHAR) RETURN INTEGER DETERMINISTIC AS
BEGIN
TotalFunctionCalls2 := TotalFunctionCalls2 + 1;
RETURN Length(SrcStr);
END;
FUNCTION GetCallCount2 RETURN INTEGER AS
BEGIN
RETURN TotalFunctionCalls2;
END;
END TestCallCount;
SELECT a,TestCallCount.StringLen('foo') FROM(
SELECT 0 as a FROM dual
UNION
SELECT 1 as a FROM dual
UNION
SELECT 2 as a FROM dual
);
SELECT TestCallCount.GetCallCount() AS TotalFunctionCalls FROM dual;
Salida:
A TESTCALLCOUNT.STRINGLEN('FOO')
---------------------- ------------------------------
0 3
1 3
2 3
3 rows selected
TOTALFUNCTIONCALLS
----------------------
3
1 rows selected
Por lo tanto la función StringLen() fue llamado tres veces en el primer caso. Ahora cuando se ejecuta con StringLen2() que se denota determinista:
SELECT a,TestCallCount.StringLen2('foo') from(
select 0 as a from dual
union
select 1 as a from dual
union
select 2 as a from dual
);
SELECT TestCallCount.GetCallCount2() AS TotalFunctionCalls FROM dual;
Resultados:
A TESTCALLCOUNT.STRINGLEN2('FOO')
---------------------- -------------------------------
0 3
1 3
2 3
3 rows selected
TOTALFUNCTIONCALLS
----------------------
1
1 rows selected
Por lo tanto la función StringLen2() sólo se llama una vez desde que fue marcado determinista.
Para una función no determinista marcado, se puede evitar esto mediante la modificación de su consulta como tal:
select a, b, c, hashed
from my_table
cross join (
select dbms_crypto.hash(utl_raw.cast_to_raw('HELLO'),3) as hashed from dual
);
Buena pregunta para DB chicos. +1 – shahkalpesh