W większości przypadków najlepiej jest unikać funkcji o wartościach skalarnych, które odwołują się do tabel, ponieważ (jak powiedzieli inni) są to w zasadzie czarne skrzynki, które należy uruchomić raz dla każdego wiersza i nie mogą być zoptymalizowane przez aparat planowania zapytań. Dlatego mają tendencję do skalowania liniowego, nawet jeśli powiązane tabele mają indeksy.
Warto rozważyć użycie funkcji z wartościami wbudowanymi w tabelę, ponieważ są one oceniane bezpośrednio z zapytaniem i można je zoptymalizować. Otrzymujesz żądaną enkapsulację, ale wydajność wklejania wyrażeń bezpośrednio w instrukcji select.
Jako efekt uboczny bycia wbudowanymi, nie mogą zawierać żadnego kodu proceduralnego (bez deklaracji @zmienna; ustaw @zmienna =..; return). Mogą jednak zwrócić kilka wierszy i kolumn.
Możesz przepisać swoje funkcje mniej więcej tak:
create function usf_GIS_GET_LAT(
@City varchar (30),
@State char (2)
)
returns table
as return (
select top 1 lat
from GIS_Location with (nolock)
where [State] = @State
and [City] = @City
);
GO
create function usf_GIS_GET_LON (
@City varchar (30),
@State char (2)
)
returns table
as return (
select top 1 LON
from GIS_Location with (nolock)
where [State] = @State
and [City] = @City
);
Składnia ich użycia jest również nieco inna:
select
Lat.Lat,
Lon.Lon
from
Address_Location with (nolock)
cross apply dbo.usf_GIS_GET_LAT(City,[State]) AS Lat
cross apply dbo.usf_GIS_GET_LON(City,[State]) AS Lon
WHERE
ID IN (SELECT TOP 100 ID FROM Address_Location WITH(NOLOCK) ORDER BY ID DESC)