В первом примере это будет выполнено только 100 раз.Вы можете проверить это, добавив отладочный вызов в функцию:
create table mytable (a, b) as select mod(level, 10), level from dual connect by level <= 50;
create or replace function myfunction(p number)
return number as
begin
dbms_output.put_line('In function for p=' || p);
return mod(p,3);
end;
/
set serveroutput on
select myfunction(b)
from mytable
where a = 1;
MYFUNCTION(B)
-------------
1
2
0
1
2
In function for p=1
In function for p=11
In function for p=21
In function for p=31
In function for p=41
Функция вызывается только для строк, которые соответствуют фильтру предложений where
.Однако, насколько я знаю, это не гарантировано.
Во втором примере все гораздо сложнее и в значительной степени зависит от оптимизатора.Для моей простой демонстрации оптимизатор (в данном случае 11gR2) сначала оценивает a
и вызывает функцию только для тех строк, которые соответствуют этому;но затем он вызывает его снова для значения списка выбора:
select myfunction(b)
from mytable
where a = 1
and myfunction(b) = 2;
MYFUNCTION(B)
-------------
2
2
In function for p=1
In function for p=11
In function for p=11
In function for p=21
In function for p=31
In function for p=41
In function for p=41
Функция вызывается для каждой из пяти строк, где a=1
, как и раньше, и для тех, где myfunction(b) = 2
она называетсяво второй раз, чтобы получить значение в наборе результатов.
Опять же, для этого примера вещи, которые вы могли бы подумать, изменили бы это поведение, но не изменились.Все они получают точно такой же вывод:
select myfunction(b)
from mytable
where myfunction(b) = 2
and a = 1;
select x
from (
select myfunction(b) as x
from mytable
where a = 1
)
where x = 2;
select x
from (
select /*+ materialize */ myfunction(b) as x
from mytable
where a = 1
)
where x = 2;
with t (x) as (
select myfunction(b)
from mytable
where a = 1
)
select x
from t
where x = 2;
Оптимизатор внутренне переписывает их все в один и тот же запрос, и вы все равно получаете все семь вызовов функций.Добавление недокументированной подсказки меняет его:
with t (x) as (
select /*+ materialize */ myfunction(b)
from mytable
where a = 1
)
select x
from t
where x = 2;
X
----------
2
2
In function for p=1
In function for p=11
In function for p=21
In function for p=31
In function for p=41
, но вы не можете (или не должны) действительно использовать или полагаться на это.
Индексация, разбиение, версия оптимизатора,статистика и т. д. будут влиять на поведение оптимизатора для вашего запроса.
И, как следует учитывать, у вас может быть индекс на основе функции или детерминированная функция ...
Итак ... это зависит.