假设您有一个PL / sql函数,它返回一些随机值,您将在sql语句中将其用作返回数据和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的一些查询以及查看解释计划,但直到现在才发现任何重大差异.
我的Oracle版本是11.2.0.3.0,如果这有任何问题.
在这种情况下检查发生了什么的好方法是使用序列(但我有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子句)并检查sequence的值:
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次.