Proszę wziąć pod uwagę następujący skrypt:
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
*/
Czy mogę polegać na f(x)
tym, że kontekst zostanie odczytany w widoku, tak jak w tym przypadku testowym uruchomionym na 10.2?
SELECT stuff FROM dbo.FuncReturningTable(param)
lub podobnie. Oracle prawdopodobnie ma równoważną funkcjonalność. Chociaż używając tego do dużych zestawów danych, uważnie monitoruję wydajność: nie jestem pewien, jak jasne musiałoby być narzędzie do planowania zapytań, aby stworzyć wydajny plan z takiej składni.Odpowiedzi:
Nie.
Jeśli ponownie napiszesz widok z filtrowaniem kontekstu względem klauzuli where (zamiast connect by), otrzymasz poprzednio ustawioną wartość dla kontekstu:
Ponieważ klauzula where jest oceniana przed zaznaczeniem kolumn, wartość przekazywana do funkcji nie jest ustawiana, dopóki nie zostanie odczytany kontekst. Lokalizacja wywołania sys_context w zapytaniu (wybierz, gdzie, grupuj według itd.) Wpłynie dokładnie na ustawienie tej wartości.
źródło
Ogólnie rzecz biorąc, nie można bezpiecznie zakładać niczego o kolejności, w jakiej DBMS zrobi rzeczy podczas oceny pojedynczej instrukcji SQL. To dlatego wiele DBMS nie pozwala funkcjom używanym w ten sposób wywoływać skutki uboczne (tj. MSSQL nie pozwala funkcjom ustawiać stanu globalnego / połączenia, który tam robisz, ani zmieniać zawartości tabeli). Szereg instrukcji musi być wykonywany w sposób, który ma sens z jednego kroku do następnego (tj. Są uruchamiane szeregowo lub w sposób, którego nie można powiedzieć, że nie były), ale w ramach pojedynczej instrukcji planista zapytań ma wolne panowanie, o ile nie wprowadza dwuznaczności tam, gdzie jeszcze nie istnieje (w twoim przykładzie niejasność już istnieje, ponieważ funkcja ma efekt uboczny wpływa na widok).
Gdyby planista zapytań był wystarczająco jasny, aby wykryć, że na widok wpływają efekty uboczne funkcji, co zrobiłby, gdybyś dołączył do innego widoku, który wywołał tę funkcję potencjalnie z różnymi wartościami wejściowymi? Może dość szybko stać się bardzo włochaty - z tego powodu ogólnie rzecz biorąc, w jakimkolwiek kontekście programowania, funkcje nie powinny mieć efektów wykraczających poza ich własne wyniki.
W tym konkretnym przykładzie powiedziałbym, że jest mało prawdopodobne, aby f (x) został wywołany jako pierwszy, ponieważ jest to część „wyświetlająca” instrukcję: zestaw wyników z widoku prawdopodobnie zostanie pobrany przed jakąkolwiek funkcją w lista kolumn do zwrócenia jest oceniana. Oczywiście będzie się to różnić w zależności od zastosowanego DBMS: nie jestem ekspertem Oracle, a wyniki testu pokazują, że funkcja wydaje się być wywoływana jako pierwsza w tych przypadkach. Byłbym jednak ostrożny, polegając na tym samym poleceniu wykonania w ramach pojedynczej instrukcji SQL - nawet jeśli zawsze działa tak, jak się teraz spodziewasz, może nie zrobić tego w przyszłych wersjach (chyba że gdzieś jest oficjalnie udokumentowane, że wykonanie zawsze pójdzie w ten sposób).
źródło
Dokumentacja obiecuje tylko, że „Optymalizator najpierw ocenia wyrażenia i warunki zawierające stałe tak dokładnie, jak to możliwe”. ( 10,2 , 11,2 ). Nie masz gwarancji, że najpierw oceni jakieś wyrażenie lub że od czasu do czasu nie zmieni tej kolejności (nowy poziom łatki w tej samej wersji?).
źródło