2015-04-09 12 views
6

Angenommen, Sie haben eine PL/SQL Funktion, die einen zufälligen Wert zurückgibt, den Sie in einer SQL sentence sowohl als zurückgegebene Daten als auch in der Order by Klausel verwenden.Oracle SQL: Wenn ich eine Funktion sowohl als ein Feld als auch in der Reihenfolge verwendet, wird es erneut ausgewertet?

Nun könnte man die Order by Klausel in drei "andere" Art und Weise schreiben:

von Index

Select Foo, 
     MyFunction(Foo) orderField 
    From FooTable 
Order By 2 

Mit "wieder" die Funktion

Select Foo, 
     MyFunction(Foo) orderField 
    From FooTable 
Order By MyFunction(Foo) 

Aufruf Durch Verwendung des Auftragsfeldalias

Select Foo, 
     MyFunction(Foo) orderField 
    From FooTable 
Order By orderField 

Der dritte Weg ist möglich, da die Order By Klausel die letzte der select werden analysiert und dann Oracle bereits kennt den Alias.

Meine Frage ist, gibt es einen Unterschied in der Verarbeitung oder Leistung dieser drei Abfragen? Würde der zweite Schritt bedeuten, dass der Anruf erneut ausgewertet wird?

Ich habe versucht, durch die Suche über die Dokumentation, um herauszufinden, und durch einige Anfragen von Toad sowie mit einem Blick auf den explain plan laufen, aber konnte keinen signifikanten Unterschied bisher finden.

Meine Oracle-Version ist 11.2.0.3.0, wenn das in irgendeiner Weise wichtig ist.

+0

Kann es vielleicht davon abhängen, ob die Funktion deterministisch ist oder nicht? (Wie auch immer, Spaltenalias ist mein Favorit.) – jarlh

+0

@jarlh, könnte gut sein. Ich bin gespannt ob jemand die Antwort kennt :-) –

Antwort

7

Eine gute Möglichkeit zu überprüfen, was in solchen Fällen passiert, ist die Verwendung von Sequenzen (aber ich habe Orakel Version 12.1). Zum Beispiel:

SQL> create sequence func_seq; 

Sequence created. 

SQL> create or replace function foo return number is 
begin 
    return func_seq.nextval; 
end; 
/

Function created. 

zuerst eine Abfrage machen, die zwei Zeilen zurück (ohne ORDER BY Klausel) und den Wert der Sequenz überprüfen:

SQL> select foo from dual connect by level <= 2; 

     FOO 
---------- 
     1 
     2 

SQL> select func_seq.currval from dual; 

    CURRVAL 
---------- 
     2 

Dann wird eine Abfrage mit 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 

In beiden Fällen wurde die Funktion 2 mal ausgeführt.
Aber wenn Ihre Funktion Argumente übernimmt, haben Sie die Aufmerksamkeit auf ihre Werte zu zahlen:

SQL> create or replace function foo(p number) return number is 
begin 
    return func_seq.nextval; 
end; 
/ 

Function created. 

Make-Abfrage mit verschiedenen Argumenten:

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 

Wie wir sehen können, wurde Funktion 4-mal ausgeführt.

+0

ziemlich netter Ansatz um meine Frage zu beantworten, danke! –

+0

@Dmitry können Sie die Reihenfolge von foo (1) * 2 überprüfen? Ich kann nicht Funktion in Sql Geige –

+0

@PavelGatnar bringen In dem Fall mit 'Order by foo (1) * 2 'Funktion wird 4 mal ausgeführt (wie Sie in Ihrer Antwort geschrieben haben). – Dmitry

2

Die Funktion wird nur einmal in Ihrem Fall ausgewertet, der Ausdruck in ORDER BY Klausel dient nur als Verweis auf eine Spalte in der SELECT Klausel. Wenn der Ausdruck nicht übereinstimmt, wird die Funktion zweimal ausgewertet, z.

Select Foo, 
     MyFunction(Foo) orderField 
From FooTable 
Order By MyFunction(Foo)*2 

Ich würde erwarten, Oracle die Ergebnisse der deterministischen Funktionen Caches (dies explizit in der Funktionsdefinition angegeben werden muss), so dass in diesen Fällen das im Cache gespeicherte Ergebnis wiederverwendet wird.

Verwandte Themen