2008-10-07 20 views
83

Załóżmy, że muszę zaimplementować fragment kodu T-SQL, który musi zwrócić tabelę jako wynik. Mogę zaimplementować funkcję zwracającą tabelę lub procedurę przechowywaną, która zwraca zestaw wierszy. Co powinienem użyć?Funkcje a procedury przechowywane

W skrócie, co chcę wiedzieć, to:

Jakie są główne różnice między funkcji i procedur przechowywanych? Jakie rozważania muszę wziąć pod uwagę przy korzystaniu z jednego lub drugiego?

+1

To wydaje się być doskonałą odpowiedzią: http://stackoverflow.com/a/1179778/365188 –

Odpowiedz

48

Jeśli najprawdopodobniej zechcesz połączyć wynik tego fragmentu kodu z innymi tabelami, oczywiście funkcja wyceniona w tabeli pozwoli Ci skomponować wyniki w pojedynczej instrukcji SELECT.

Generalnie istnieje hierarchia (zobacz < Funkcja TV < Zapisany Proc). Możesz zrobić więcej w każdym z nich, ale możliwość skomponowania danych wyjściowych i optymalizatora, aby uzyskać naprawdę zaangażowany spadek w miarę wzrostu funkcjonalności.

Użyj więc tego, który minimalnie pozwala ci wyrazić pożądany rezultat.

4

Osobiście używam funkcji wycenianych w tabeli, gdy wszystko, co wracam, to pojedyncza tabela bez żadnych wpływów. Zasadniczo traktuję je jak sparametryzowane widoki.

Jeśli potrzebuję wielu zestawów rekordów zwróconych lub są wartości zaktualizowane w tabelach, używam procedury przechowywanej.

Moje 2 centów

6

Jeśli masz funkcję można użyć go jako część swojej SQL, na przykład

SELECT function_name(field1) FROM table 

To nie działa w ten sposób do procedur przechowywanych.

+1

myślę, że on mówił o funkcje, które zwracają wartości tabeli. – wcm

+1

Cóż, ogólnie mówię. Ale w moim konkretnym przypadku znajduję się obecnie pomiędzy procedurą składowaną lub funkcją o wartości tabelarycznej. – Auron

48

funkcje muszą być deterministyczny i nie mogą być wykorzystywane do wprowadzania zmian w bazie danych, natomiast procedury przechowywane pozwalają zrobić wstawki i aktualizacji itp

należy ograniczyć korzystanie z funkcji, ponieważ stanowią one ogromne problem skalowalności dla dużych, złożonych zapytań. Stanowią one rodzaj "czarnej skrzynki" dla optymalizatora zapytań, a zobaczysz ogromne różnice w wydajności między używaniem funkcji i po prostu wstawienie kodu do zapytania.

Są one jednak bardzo przydatne w przypadku zwrotów zwracanych przez tabelę w bardzo szczególnych przypadkach.

Jeśli chcesz przeanalizować listę rozdzielaną przecinkami, aby zasymulować przekazanie tablicy do procedury, funkcja może zmienić tę listę w tabelę. Jest to powszechna praktyka w przypadku Sql Server 2005, ponieważ nie możemy jeszcze przekazywać tabel do procedur składowanych (możemy z 2008 r.).

+1

Ale możesz wysłać XML do procedury przechowywanej: http://stackoverflow.com/questions/144550/sql-server-dynamic-where-clause – roosteronacid

+2

Niepoprawne, większość funkcji serwera SQL jest niedeterministyczna, np. Getdate w MS- Serwer SQL. Tylko funkcje ODBC są funkcjami kanonicznymi (= znacznie szybsze + indeksowalne) ... Ale jesteś bardzo poprawny, należy ograniczyć korzystanie z funkcji w zapytaniach w największym możliwym stopniu ze względu na wydajność. –

1

To zależy :) Jeśli chcesz użyć wyniku z tabelą w innej procedurze, lepiej jest użyć funkcji TableValued. Jeśli wyniki są dla klienta, przechowywany proces jest zwykle lepszym rozwiązaniem.

41

From the docs:

Jeśli procedura składowana spełnia następujące kryteria, jest dobrym kandydatem do być przepisany jako wycenione tabela funkcji:

  • Logika jest wyrazić w pojedynczym Instrukcja SELECT, ale jest procedura składowana, a nie widok, tylko ze względu na potrzebę parametrów.

  • Procedura składowana nie wykonuje operacji aktualizacji, z wyjątkiem zmiennych tabel.

  • Nie ma potrzeby dynamicznych instrukcji EXECUTE.

  • Procedura składowana zwraca jeden zestaw wyników.

  • Podstawowym celem procedury składowanej jest utworzenie wyników pośrednich, które mają zostać załadowane do tabeli tymczasowej, a następnie zapytanie SELECT.

1

bym perfromance testu obu. Jest prawdopodobne, że metoda sp lub wyprowadzona tabela będzie znacznie szybsza niż funkcja, a jeśli tak, to należy zastosować podejście. Zasadniczo unikam funkcji, ponieważ mogą to być świnie wydajnościowe.

4

Jak wspomniano powyżej, funkcje są bardziej czytelne/sk/self dokumentowanie, ale są mniej wydajnych w ogóle, a może być poważnie mniej wydajnych jeśli się ponieść z nimi łączy, takich jak

SELECT * 
FROM dbo.tvfVeryLargeResultset1(@myVar1) tvf1 
INNER JOIN dbo.tvfVeryLargeResultset1(@myVar2) tvf2 
    ON (tvf1.JoinId = tvf2.JoinId) 

Często , po prostu trzeba zaakceptować nadmiarowość kodu że tvf mogłoby wyeliminować (w niedopuszczalnym kosztem wydajności.)

Jeden inny punkt ja jeszcze nie widziałem wspomniano jest to, że nie można korzystać z bazy danych państwowego zmienia temp tabele wewnątrz wielostaniowego tvf. Najbardziej funkcjonalnym mechanizmem odpowiadającym tabeli tymczasowej jest zmienna niepubliczna, w zmiennej tabeli pamięci, a w przypadku dużych zestawów danych tabela tymczasowa będzie prawdopodobnie bardziej wydajna niż zmienna tabeli. (Inne alternatywy obejmują tabele dynamiczne & pospolitych wyrażeń wycenianych w tabeli, ale na pewnym poziomie złożoności, te przestają być dobrym rozwiązaniem IMO.)

+0

Zrobiłeś dobry punkt! Dzięki! – Auron

5

Przeprowadziłem kilka testów z długim biegiem logiki, z tym samym bitem kod (długa instrukcja SELECT) działająca zarówno w funkcji wycenianej w tabeli, jak i w procedurze zapisanej, oraz prostej operacji EXEC/SELECT i każdej przeprowadzonej identycznie.

Moim zdaniem, zawsze używaj funkcji wycenianej z tabeli, a nie procedury przechowywanej, aby zwrócić zestaw wyników, ponieważ sprawia, że ​​logika jest znacznie łatwiejsza i czytelniejsza w zapytaniach, które następnie dołączają do nich, i umożliwia ponowne użycie tej samej logiki. Aby uniknąć zbyt wielkim hitem wydajności, często używam „opcjonalne” parametry (czyli można przekazać NULL do nich), aby włączyć funkcję wrócić zestaw wyników będzie szybsze, np:

CREATE FUNCTION dbo.getSitePermissions(@RegionID int, @optPersonID int, optSiteID int) 
AS 
RETURN 
    SELECT DISTINCT SiteID, PersonID 
    FROM dbo.SiteViewPermissions 
    WHERE (@optPersonID IS NULL OR @optPersonID = PersonID) 
    AND (@optSiteID IS NULL OR @optSiteID = SiteID) 
    AND @RegionID = RegionID 

ten sposób może korzystać z tej funkcji w wielu różnych sytuacjach i nie należy przyjmować ogromnych wyników.Wierzę, że to jest bardziej wydajny niż filtrowanie potem:

SELECT * FROM dbo.getSitePermissions(@RegionID) WHERE SiteID = 1 

Użyłem tej techniki w kilku funkcjach, czasami z długiej listy „opcjonalne” parametry tego typu.

8
  1. Procedura może powrócić zero lub wartości n, podczas gdy funkcja zwraca jedna wartość, która jest konieczna.

  2. Procedury mogą mieć parametry wejściowe/wyjściowe, podczas gdy funkcje mogą mieć tylko parametry wejściowe.

  3. Procedura umożliwia wybranie polecenia select i DML, podczas gdy funkcja umożliwia tylko wybranie w nim instrukcji.

  4. Funkcje można wywoływać z procedury, a procedury nie mogą być wywoływane z funkcji .

  5. Wyjątkiem może być blok try-catch w procedurze, podczas gdy blok try-catch nie może być używany w funkcji.

  6. Możemy przejść do zarządzania transakcjami w procedurze, podczas gdy my nie możemy wejść do funkcji.

  7. Procedury nie można wykorzystać w instrukcji select, a funkcję można osadzić w instrukcji select.

  8. UDF (User Defined funkcja) może być stosowany w sprawozdaniu SQL Anywhere w sekcji WHERE/HAVING/SELECT natomiast procedur składowanych nie może być.

  9. UDF, które zwracają tabele, można traktować jako inny zestaw wierszy. To może być używane w JOIN s z innymi tabelami.

  10. Obiekty UDF typu Inline mogą być widokami, które pobierają parametry i mogą być używane w JOIN s i innych operacjach zestawów wierszy.

10

Zamierzam napisać kilka interesujących różnic między procedurami przechowywanymi i funkcjami.

  • Możemy używać funkcji w wybranych zapytaniach, ale nie możemy używać przechowywanych procedur w zapytaniach wybranych.
  • Nie możemy używać funkcji innych niż deterministyczne w funkcjach, ale możemy używać funkcji niedeterministycznych w procedurach przechowywanych. Teraz pojawia się pytanie, co nie jest funkcja deterministyczny .. Ans jest: -

    Non deterministyczny funkcja jest funkcją, która zwraca różne wyjścia dla tych samych wartości wejściowych w różnym czasie, jak getdate(). Zawsze zwraca inną wartość po uruchomieniu.

    Wyjątek: -

    wcześniejszych wersjach SQL Server przed SQL 2000 nie pozwalają używać getdate() funkcji w funkcji zdefiniowanych przez użytkownika, ale wersja 2005 i nowsze pozwala nam korzystać getdate() funkcja w ramach funkcji zdefiniowanej przez użytkownika.

    Newid() to kolejny przykład funkcji niedeterministycznej, ale nie można go używać w funkcjach zdefiniowanych przez użytkownika, ale możemy go użyć w procedurze przechowywanej.

  • Możemy użyć DML (INSERT, UPDATE, usuwanie) oświadczenia w ramach procedury przechowywanej ale nie możemy użyć instrukcji DML w funkcji fizycznych na stołach lub stałych tablicach. Jeśli chcemy wykonywać operacje DML w funkcjach możemy to zrobić za pomocą zmiennych tabelowych, a nie tabel stałych.

  • Nie możemy używać obsługi błędów w ramach funkcji, ale możemy wykonać błąd w procedurach przechowywanych w zakresie .

+0

W jaki sposób operacje DML są obsługiwane w funkcjach MySQL? –