Bitte beachten Sie das folgende Skript:
create or replace function f(p_limit in integer) return integer as
begin
set_global_context ('limit', p_limit);
return p_limit;
end;
/
create view v as
select level as val from dual connect by level<=sys_context('global_context','limit');
select f(2), v.* from v;
/*
F(2) VAL
---------------------- ----------------------
2 1
2 2
*/
select f(4), v.* from v;
/*
F(4) VAL
---------------------- ----------------------
4 1
4 2
4 3
4 4
*/
Kann ich mich darauf verlassen f(x)
, ausgeführt zu werden, bevor der Kontext in der Ansicht gelesen wird, wie es in diesem Testfall unter 10.2 der Fall war?
SELECT stuff FROM dbo.FuncReturningTable(param)
oder ähnliches. Oracle hat wahrscheinlich eine gleichwertige Funktionalität. Wenn ich dies über große Datenmengen verwende, würde ich die Leistung sorgfältig überwachen: Ich bin mir nicht sicher, wie hell der Abfrageplaner sein müsste, um aus einer solchen Syntax einen effizienten Plan zu erstellen.Antworten:
Nein.
Wenn Sie Ihre Ansicht mit der Kontextfilterung anhand der where-Klausel (anstelle der connect by) neu schreiben, erhalten Sie den zuvor festgelegten Wert für den Kontext:
Da die where-Klausel vor der Auswahl der Spalten ausgewertet wird, wird der an die Funktion übergebene Wert erst nach dem Lesen des Kontexts festgelegt. Der Speicherort des Aufrufs sys_context in Ihrer Abfrage (auswählen, wo, gruppieren nach usw.) wirkt sich genau darauf aus, wann dieser Wert festgelegt wird.
quelle
Im Allgemeinen können Sie nicht sicher annehmen, in welcher Reihenfolge Ihr DBMS bei der Auswertung einer einzelnen SQL-Anweisung vorgeht. Aus diesem Grund lassen viele DBMS nicht zu, dass auf diese Weise verwendete Funktionen Nebenwirkungen haben (dh MSSQL erlaubt Funktionen nicht, den globalen / Verbindungsstatus festzulegen, den Sie dort ausführen, oder den Tabelleninhalt zu ändern). Eine Reihe von Anweisungen muss so ausgeführt werden, dass sie von einem Schritt zum nächsten sinnvoll sind (dh sie werden seriell ausgeführt oder so, dass Sie nicht erkennen können, dass dies nicht der Fall ist), aber innerhalb einer einzelnen Anweisung der Abfrageplaner hat freie Hand, solange es keine Mehrdeutigkeit einführt, wo es noch nicht existiert (in Ihrem Beispiel existiert bereits Mehrdeutigkeit, weil die Funktion einen Nebeneffekt hat, der die Ansicht beeinflusst).
Wenn der Abfrageplaner hell genug wäre, um zu erkennen, dass die Ansicht von den Nebenwirkungen der Funktion betroffen ist, was würde er tun, wenn Sie einer anderen Ansicht beitreten würden, die diese Funktion möglicherweise mit unterschiedlichen Eingabewerten aufruft? Es könnte ziemlich schnell sehr haarig werden - deshalb sollten Funktionen in jedem Programmierkontext im Allgemeinen keine Auswirkungen haben, die über ihre eigene Ausgabe hinausgehen.
In diesem speziellen Beispiel würde ich sagen, dass es unwahrscheinlich ist, dass f (x) zuerst aufgerufen wird, da es sich um den "Anzeige" -Teil der Anweisung handelt: Die Ergebnismenge aus der Ansicht wird wahrscheinlich vor Funktionen innerhalb der abgerufen Die Liste der zurückzugebenden Spalten wird ausgewertet. Dies hängt natürlich vom verwendeten DBMS ab: Ich bin kein Oracle-Experte, und Ihre Testergebnisse zeigen, dass die Funktion in diesen Fällen anscheinend zuerst aufgerufen wird. Ich würde mich jedoch davor hüten, mich auf die Ausführungsreihenfolge innerhalb einer einzelnen SQL-Anweisung zu verlassen - auch wenn sie in zukünftigen Revisionen immer so funktioniert, wie Sie es derzeit erwarten (es sei denn, es ist offiziell irgendwo dokumentiert, dass die Ausführung immer stattfinden wird) hier herum).
quelle
Die Dokumentation verspricht nur, dass "der Optimierer zuerst Ausdrücke und Bedingungen, die Konstanten enthalten, so vollständig wie möglich bewertet." ( 10.2 , 11.2 ). Es kann nicht garantiert werden, dass zuerst ein bestimmter Ausdruck ausgewertet wird oder dass diese Reihenfolge nicht von Zeit zu Zeit geändert wird (ein neues Patchlevel innerhalb derselben Version?).
quelle