Funkcje i procedury przechowywane służą odrębnym celom. Chociaż nie jest to najlepsza analogia, funkcje można postrzegać dosłownie jak każdą inną funkcję, której można by użyć w dowolnym języku programowania, ale przechowywane procy przypominają raczej poszczególne programy lub skrypt wsadowy.
Funkcje zwykle mają wyjście i opcjonalnie wejścia. Dane wyjściowe można następnie wykorzystać jako dane wejściowe do innej funkcji (wbudowany SQL Server, taki jak DATEDIFF, LEN itp.) Lub jako predykat do zapytania SQL - np . SELECT a, b, dbo.MyFunction(c) FROM table
Lub SELECT a, b, c FROM table WHERE a = dbo.MyFunc(c)
.
Przechowywane procy są używane do łączenia zapytań SQL w transakcji i interfejsu ze światem zewnętrznym. Frameworki takie jak ADO.NET itp. Nie mogą bezpośrednio wywoływać funkcji, ale mogą bezpośrednio wywoływać przechowywany proc.
Funkcje mają jednak ukryte niebezpieczeństwo: mogą być niewłaściwie używane i powodować dość nieprzyjemne problemy z wydajnością: rozważ to zapytanie:
SELECT * FROM dbo.MyTable WHERE col1 = dbo.MyFunction(col2)
Gdzie MyFunction jest zadeklarowane jako:
CREATE FUNCTION MyFunction (@someValue INTEGER) RETURNS INTEGER
AS
BEGIN
DECLARE @retval INTEGER
SELECT localValue
FROM dbo.localToNationalMapTable
WHERE nationalValue = @someValue
RETURN @retval
END
Tutaj dzieje się tak, że funkcja MyFunction jest wywoływana dla każdego wiersza w tabeli MyTable. Jeśli MyTable ma 1000 wierszy, to kolejne 1000 zapytań ad-hoc względem bazy danych. Podobnie, jeśli funkcja jest wywoływana, gdy jest określona w specyfikacji kolumny, funkcja będzie wywoływana dla każdego wiersza zwróconego przez WYBÓR.
Musisz więc uważnie pisać funkcje. Jeśli wybierzesz opcję WYBIERZ z tabeli w funkcji, musisz zadać sobie pytanie, czy można ją lepiej wykonać za pomocą JOIN w nadrzędnym przechowywanym proc lub jakimś innym konstrukcie SQL (takim jak CASE ... WHEN ... ELSE ... KONIEC).