假设您有一个PL/SQL
函数,它返回一些随机值,您将在SQL sentence
中使用它作为返回数据和Order by
子句。
现在你可以在三个"不同的"中编写Order by
条款。方法:
按索引
Select Foo,
MyFunction(Foo) orderField
From FooTable
Order By 2
再次呼叫""功能
Select Foo,
MyFunction(Foo) orderField
From FooTable
Order By MyFunction(Foo)
使用订单字段别名
Select Foo,
MyFunction(Foo) orderField
From FooTable
Order By orderField
第三种方式是可能的,因为Order By
子句是要解析的select的最后一个,然后Oracle已经知道了别名。
我的问题是,这三个查询的处理或性能有什么不同吗?特别是,第二个意味着是否会再次评估MyFunction
来电?
我试图通过搜索文档,并运行来自 Toad 的一些查询以及查看explain plan
来查找,但直到现在才发现任何重大差异。
我的Oracle版本是11.2.0.3.0,如果这有任何影响。
答案 0 :(得分:7)
在这种情况下检查发生了什么的好方法是使用序列(但我有oracle版本12.1)。例如:
SQL> create sequence func_seq;
Sequence created.
SQL> create or replace function foo return number is
begin
return func_seq.nextval;
end;
/
Function created.
首先,创建一个返回两行(没有ORDER BY
子句)的查询并检查序列的值:
SQL> select foo from dual connect by level <= 2;
FOO
----------
1
2
SQL> select func_seq.currval from dual;
CURRVAL
----------
2
然后使用ORDER BY
的查询:
SQL> select foo from dual connect by level <= 2 order by foo;
FOO
----------
3
4
SQL> select func_seq.currval from dual;
CURRVAL
----------
4
在这两种情况下,功能被执行了2次 但是如果你的函数需要参数,你必须注意它们的值:
SQL> create or replace function foo(p number) return number is
begin
return func_seq.nextval;
end;
/
Function created.
使用不同的参数进行查询:
SQL> select foo(1) from dual connect by level <= 2 order by foo(2);
FOO(1)
----------
6
8
SQL> select func_seq.currval from dual;
CURRVAL
----------
8
正如我们所见,功能被执行了4次。
答案 1 :(得分:2)
在您的情况下,函数仅评估一次,ORDER BY
子句中的表达式仅用作对SELECT
子句中列的引用。
当表达式不匹配时,函数将被评估两次,例如
Select Foo,
MyFunction(Foo) orderField
From FooTable
Order By MyFunction(Foo)*2
我希望Oracle缓存确定性函数的结果(必须在函数定义中明确说明),因此在这种情况下,重用缓存结果。