Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
Имеем некую фунцию
create or replace function F_temp(id in NUMBER)
  return VARCHAR2 
is
begin
  DBMS_OUTPUT.Put_line('ID = ' || id);
  return id;
end F_temp;
если вызывать так
select z, z+1 from (select F_temp(1) Z  from dual);
то обращени к функции происходит дважды.
Если же так:
select z, z+1 from (select max(F_temp(1)) Z  from dual);
то функция вызывается один раз.
ПОЧЕМУ?
17 июн 09, 11:05    [7308834]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
ILoveCoffee
Member

Откуда: Astana
Сообщений: 986
>обращени к функции происходит дважды.
StayAtHome,
С чего взяли?
17 июн 09, 11:13    [7308901]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
Jannny
Member

Откуда: Спб
Сообщений: 6424
почтому что аггрегация материализует подзапрос, то есть не дает переписать так:
select F_temp(1), F_temp(1)+1 from
17 июн 09, 11:18    [7308949]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
ILoveCoffee
Member

Откуда: Astana
Сообщений: 986
ILoveCoffee,
Хы увидел дбмс, задумался.
17 июн 09, 11:18    [7308951]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
Elic
Member

Откуда:
Сообщений: 29989
StayAtHome
ПОЧЕМУ?
RTFM How the CBO Merges Views (FAQ)
17 июн 09, 11:26    [7309025]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
StayAtHome
Имеем некую фунцию
create or replace function F_temp(id in NUMBER)
  return VARCHAR2 
is
begin
  DBMS_OUTPUT.Put_line('ID = ' || id);
  return id;
end F_temp;
если вызывать так
select z, z+1 from (select F_temp(1) Z  from dual);
то обращени к функции происходит дважды.
Если же так:
select z, z+1 from (select max(F_temp(1)) Z  from dual);
то функция вызывается один раз.
ПОЧЕМУ?

собственно, уже ответили..

потому, что, с точки зрения оптимизатора, вы именно этого хотите
см. на
select z, z+1 from (select F_temp(1) Z from dual where rownum>0;
17 июн 09, 11:40    [7309141]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
тут скобочка похерилась, а она, как раз, важная
select z, z+1 from (select F_temp(1) Z from dual where rownum>0);
17 июн 09, 11:45    [7309186]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
orawish
тут скобочка похерилась, а она, как раз, важная
select z, z+1 from (select F_temp(1) Z from dual where rownum>0);

Пробовал и так -- тройной вызов получается (Orace 10)
17 июн 09, 11:48    [7309212]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
StayAtHome
orawish
тут скобочка похерилась, а она, как раз, важная
select z, z+1 from (select F_temp(1) Z from dual where rownum>0);

Пробовал и так -- тройной вызов получается (Orace 10)


если вы (как обычно бывает) хотите чтобы функция вызывалась один раз, то
с 9i есть для этого (ломовой) приём явной материализации.
with t as (select --+ materialize
F_temp(1) Z from dual)
select z, z+1 from t;
17 июн 09, 11:53    [7309255]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
StayAtHome
..
Пробовал и так -- тройной вызов получается (Orace 10)

еще хочу сказать, что я не то чтобы вам не верю, но диагостика/оутпут у вас такой, что
вы легко можете увидеть то, чего нет
17 июн 09, 11:57    [7309276]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
orawish
StayAtHome
..
Пробовал и так -- тройной вызов получается (Orace 10)

еще хочу сказать, что я не то чтобы вам не верю, но диагостика/оутпут у вас такой, что
вы легко можете увидеть то, чего нет

Сам в шоке. Пробовал в Toad for Oracle 9.6... Ща попробую где-нибуть в sqlplus
17 июн 09, 12:26    [7309548]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
orawish
если вы (как обычно бывает) хотите чтобы функция вызывалась один раз, то
с 9i есть для этого (ломовой) приём явной материализации.
with t as (select --+ materialize
F_temp(1) Z from dual)
select z, z+1 from t;

Интересно... Помогло, конечно, но попробовал также вот так
select z, z+1  from (select /*+ materialize */ F_temp(1) Z  from dual);
Тут хинт не сработал. Может тыкнете еще и в FAQ по WITH (плз, не сильно больно)
17 июн 09, 12:31    [7309582]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
orawish
StayAtHome
..
Пробовал и так -- тройной вызов получается (Orace 10)

еще хочу сказать, что я не то чтобы вам не верю, но диагостика/оутпут у вас такой, что
вы легко можете увидеть то, чего нет

Вот...
SQL*Plus: Release 10.2.0.1.0 - Production on Wed Jun 17 11:35:59 2009

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> create or replace function F_temp(id in NUMBER)
  2    return VARCHAR2 
  3  is
  4  begin
  5    DBMS_OUTPUT.Put_line('ID = ' || id);
  6    return id;
  7  end F_temp;
  8  /

Function created.

SQL> set serverout on;
SQL> select z, z+1 from (select F_temp(1) Z from dual where rownum>0);

Z
--------------------------------------------------------------------------------
       Z+1
----------
1
         2


ID = 1
ID = 1
ID = 1
17 июн 09, 12:37    [7309633]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
StayAtHome
..Тут хинт не сработал. Может тыкнете еще и в FAQ по WITH (плз, не сильно больно)

ну дак он только внутри with кляузы живёт, (с inline в паре).
а ткнуть - в доке родной он как недокументированный вроде и до сих пор не проявился,
но так как популярный - во всех опусах про хинты присутствует.

Читать про него особо нечего. Вставить в with кляузу + проверить, что в плане появился шаг
темптейблтрансформейшен.
17 июн 09, 12:56    [7309805]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
orawish
select z, z+1 from (select F_temp(1) Z from dual where rownum>0);

Еще один вопрос остается открытым... у Вас с rownum>0 -- вызов функции происходит один раз?
17 июн 09, 16:19    [7311441]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
StayAtHome
orawish
select z, z+1 from (select F_temp(1) Z from dual where rownum>0);

Еще один вопрос остается открытым... у Вас с rownum>0 -- вызов функции происходит один раз?


гы.. когда как от одного до таки трёх
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> 
SQL> set serveroutput on
SQL> begin
  2  for c1 in (
  3  select z, z+1 from (select F_temp(1) Z from dual where rownum>0))loop
  4    null;
  5  end loop;
  6  end;
  7  /
ID = 1

Процедура PL/SQL успешно завершена.

SQL> select z, z+1 from (select F_temp(1) Z from dual where rownum>0);

Z
--------------------------------------------------------------------------------
       Z+1
----------
1
         2


ID = 1
ID = 1
ID = 1

вот - недавно тема была ~близкая
17 июн 09, 17:03    [7311813]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
orawish,
да, видел эту тему, собственно получил тройной вызов по rownum, понял, что чайник :) и создал эту.
17 июн 09, 17:43    [7312135]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
Bfink
Member

Откуда: Москва
Сообщений: 2797
StayAtHome

А попробуйте функцию из той темы с sequence, тоже будет три раза?
17 июн 09, 17:57    [7312242]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
Bfink
StayAtHome
А попробуйте функцию из той темы с sequence, тоже будет три раза?

Там много примеров, какую именно?
17 июн 09, 18:28    [7312407]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
Bfink
Member

Откуда: Москва
Сообщений: 2797
Последовательность -
Create sequence seq1;


Функция -
create function seq1_ return number as
nn number;
begin
select seq1.nextval a into nn from dual;
return nn;
end;

Запрос -

Select a a1, a a2 from (
select seq1_() a, rownum from dual
);

Результат должен быть a1=a2
17 июн 09, 18:51    [7312492]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
Bfink,
SQL*Plus: Release 10.2.0.1.0 - Production on Thu Jun 18 09:21:22 2009

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> Create sequence seq1;

Sequence created.

SQL> create function seq1_ return number as
  2  nn number;
  3  begin
  4  select seq1.nextval a into nn from dual;
  5  return nn;
  6  end;
  7  /

Function created.

SQL> Select a a1, a a2 from (
  2  select seq1_() a, rownum from dual
  3  );

        A1         A2
---------- ----------
         1          1

SQL> 
18 июн 09, 10:25    [7314026]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
Bfink
Member

Откуда: Москва
Сообщений: 2797
StayAtHome,

Такой запрос должен обеспечивать однократный вызов функции
18 июн 09, 10:59    [7314209]     Ответить | Цитировать Сообщить модератору
 Re: Повторный вызов функции в запросе  [new]
StayAtHome
Member

Откуда:
Сообщений: 67
Bfink
StayAtHome,

Такой запрос должен обеспечивать однократный вызов функции


Увы... Работает только вариант с хинтом, либо обертка из агрегатной MAX
19 июн 09, 14:31    [7320890]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить