In de meeste gevallen is het het beste om scalaire functies te vermijden die verwijzen naar tabellen, omdat het (zoals anderen al zeiden) in feite zwarte dozen zijn die één keer voor elke rij moeten worden uitgevoerd en niet kunnen worden geoptimaliseerd door de queryplan-engine. Daarom hebben ze de neiging om lineair te schalen, zelfs als de bijbehorende tabellen indexen hebben.
U kunt overwegen een functie met inline-tabelwaarde te gebruiken, omdat deze inline met de query worden geëvalueerd en kunnen worden geoptimaliseerd. U krijgt de gewenste inkapseling, maar de prestatie van het plakken van de uitdrukkingen in de select-instructie.
Als neveneffect van het feit dat ze inline zijn, kunnen ze geen procedurele code bevatten (no declare @variable; set @variable =..; return). Ze kunnen echter meerdere rijen en kolommen retourneren.
Je zou je functies ongeveer als volgt kunnen herschrijven:
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
);
De syntaxis om ze te gebruiken is ook een beetje anders:
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)