Ho eseguito alcuni test con un po 'di logica a lunga esecuzione, con lo stesso bit di codice (una lunga istruzione SELECT) in esecuzione sia in una funzione con valore di tabella che in una procedura memorizzata e in un EXEC / SELECT diretto e ciascuno eseguito in modo identico.
A mio parere, utilizza sempre una funzione con valori di tabella anziché una stored procedure per restituire un set di risultati, poiché rende la logica molto più semplice e leggibile nelle query che successivamente si uniscono a esse e consente di riutilizzare la stessa logica. Per evitare un impatto eccessivo sulle prestazioni, utilizzo spesso parametri "opzionali" (ovvero puoi passare loro NULL) per consentire alla funzione di restituire il set di risultati in modo più rapido, ad esempio:
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
In questo modo puoi utilizzare questa funzione per molte situazioni diverse e non subire un enorme calo delle prestazioni. Credo che questo sia più efficiente del filtraggio in seguito:
SELECT * FROM dbo.getSitePermissions(@RegionID) WHERE SiteID = 1
Ho utilizzato questa tecnica in diverse funzioni, a volte con un lungo elenco di parametri "opzionali" di questo tipo.