In SQL è possibile implementare la logica aziendale attraverso funzioni definite dall'utente (User Defined Functions, UDF), che consentono di spostare una parte dei calcoli e delle regole aziendali nel database.
Le funzioni scalari restituiscono un singolo valore e vengono richiamate nelle espressioni — ad esempio, per calcolare un totale basato su parametri:
CREATE FUNCTION dbo.GetDiscount(@price DECIMAL(10,2), @loyaltyLevel INT) RETURNS DECIMAL(10,2) AS BEGIN RETURN @price * CASE WHEN @loyaltyLevel = 1 THEN 0.95 WHEN @loyaltyLevel = 2 THEN 0.90 ELSE 1.0 END END; -- Esempio di utilizzo: SELECT Name, dbo.GetDiscount(Price, LoyaltyLevel) AS DiscountPrice FROM Products;
Le funzioni tabellari restituiscono un set di righe (tabella):
CREATE FUNCTION dbo.ActiveOrders(@userId INT) RETURNS TABLE AS RETURN ( SELECT * FROM Orders WHERE UserId = @userId AND Status = 'Active' ); -- Utilizzo: SELECT * FROM dbo.ActiveOrders(123);
Differenze, limitazioni e raccomandazioni:
Qual è la differenza tra una funzione tabellare INLINE e una funzione tabellare multi-statement? Come influisce questa scelta sulle prestazioni?
Risposta ed esempio:
-- INLINE CREATE FUNCTION dbo.InlineActiveOrders(@userId INT) RETURNS TABLE AS RETURN ( SELECT * FROM Orders WHERE UserId = @userId AND Status = 'Active' ); -- Multi-statement CREATE FUNCTION dbo.MultiActiveOrders(@userId INT) RETURNS @result TABLE (...) AS BEGIN INSERT INTO @result SELECT ... -- logica RETURN END
Storia
Progetto: Analisi finanziaria.
Abbiamo utilizzato UDF scalari nella parte SELECT di una query di report su un grande insieme di tabelle: SELECT Amount, dbo.CalcTax(Amount, Type) FROM Transactions. La query impiegava 5-10 minuti a causa dell'elaborazione riga per riga delle UDF. Riscritto utilizzando un CASE integrato: il tempo è sceso a secondi.
Storia
Progetto: E-commerce. Per cercare i carrelli degli utenti abbiamo utilizzato funzioni tabellari multi-statement, dove c'era una logica di filtrazione in più fasi. Si è scoperto che SQL non costruiva un piano ottimale e generava una scansione, anche quando era necessario un solo elemento. La sostituzione con una funzione INLINE ha immediatamente accelerato le query di 50 volte.
Storia
Progetto: CRM. Abbiamo trasferito la logica aziendale per l'accredito dei bonus in una complessa UDF. Dopo un paio di mesi ci siamo resi conto che le formule aziendali erano cambiate, e aggiornare la funzione era complicato a causa del forte legame con i dati. In un prodotto iterativo, le UDF hanno portato a costi elevati per il coordinamento delle modifiche tra il backend e il DB.