首先强制子查询

时间:2013-01-31 20:28:23

标签: sql oracle oracle10g oraclereports

我正在创建一个多次使用2个嵌入式服务器功能的查询。

问题:函数搜索一个相当大的表,它们需要很长时间才能执行。

目标:使用子查询就像它是一个表一样,这样我就可以引用列而不运行该函数来多次生成列。

Example Pseudocode:

Select general.column1, general.column2, general.column1-general.column2
from (select package.function1('I take a long time') column1, 
      package.function2('I take even longer') column2,
      normal_column
      from bigtable) general;

Select general.column1, general.column2, general.column1-general.column2 from (select package.function1('I take a long time') column1, package.function2('I take even longer') column2, normal_column from bigtable) general;

当我运行我的代码时,general.column1将引用column1语句中的函数,而不是它返回的数据(这最终是我所追求的)。

我对SQL很新,所以感谢任何帮助,如果您需要更多信息,我会尽力提供。

谢谢!

2 个答案:

答案 0 :(得分:5)

我建议你使用子查询因子。第一个子查询只执行一次,然后用于查询的其余部分。

WITH function_result AS
  (SELECT package.function1('I take a long time') column1 
   ,      package.function2('I take even longer') column2
   FROM   dual)
SELECT function_result.column1
,      function_result.column2
,      function_result.column1 - function_result.column2
,      bigtable.normal_column
FROM   bigtable

答案 1 :(得分:4)

一般来说,你想要做的是在这种情况下采取标量子查询缓存的优点。

即。放:

Select general.column1, general.column2, general.column1-general.column2
  from (select (select package.function1('I take a long time') from dual) column1, 
               (select package.function2('I take even longer') from dual) column2,
               normal_column
          from bigtable) general;
如果它是确定性的,那么

将函数描述为deterministic也会有所帮助。

一个小例子:

SQL> create or replace function testfunc(i varchar2)
  2  return varchar2
  3  is
  4  begin
  5    dbms_application_info.set_client_info(userenv('client_info')+1 );
  6    return 'hi';
  7  end;
  8  /

Function created.

现在让我们像你一样测试对函数的调用:

SQL> exec dbms_application_info.set_client_info(0);

PL/SQL procedure successfully completed.

SQL> set autotrace traceonly
SQL> select *
  2    from (select testfunc(owner) a
  3            from all_objects);

57954 rows selected.

SQL> select userenv('client_info') from dual;

USERENV('CLIENT_INFO')
----------------------------------------------------------------
57954

该函数被称为57954次(每行一次)。现在让我们使用标量缓存:

SQL> exec dbms_application_info.set_client_info(0);

PL/SQL procedure successfully completed.

SQL> select *
  2    from (select (select testfunc(owner) from dual) a
  3            from all_objects);

57954 rows selected.

SQL> select userenv('client_info') from dual;

USERENV('CLIENT_INFO')
----------------------------------------------------------------
178

178次来电而不是57k! 在你的情况下,你只显示你有一个文字,没有每行变化的输入(如果是这种情况,使用标量缓存后的调用次数应为1)。

如果我们添加确定性:

SQL> create or replace function testfunc(i varchar2)
  2  return varchar2 deterministic
  3  is
  4  begin
  5    dbms_application_info.set_client_info(userenv('client_info')+1 );
  6    return 'hi';
  7  end;
  8  /

Function created.

SQL> exec dbms_application_info.set_client_info(0);

PL/SQL procedure successfully completed.

SQL> select *
  2    from (select (select testfunc(owner) from dual) a
  3            from all_objects);

57954 rows selected.

SQL> select userenv('client_info') from dual;

USERENV('CLIENT_INFO')
----------------------------------------------------------------
55

现在降到55.在11g中我们有result_cache我们可以用它来代替确定性,这会减少对子序列运行的调用到0次调用。