ProgrammazioneSviluppatore Backend

Come implementare complesse regole aziendali e calcoli direttamente in SQL utilizzando le funzioni definite dall'utente (User Defined Functions, UDF)? Quali sono le differenze e le limitazioni tra le UDF scalari e quelle tabellari, quando è opportuno utilizzarle e quando è meglio implementare una logica simile in un'applicazione esterna?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

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:

  • Le UDF scalari hanno spesso basse prestazioni su grandi set di dati, poiché vengono chiamate riga per riga;
  • Le UDF tabellari si integrano meglio nei piani di query e possono essere utilizzate come tabelle normali;
  • La logica che richiede accesso a risorse esterne o una complessa elaborazione aziendale è meglio spostarla al di fuori di SQL.

Domanda ingannevole.

Qual è la differenza tra una funzione tabellare INLINE e una funzione tabellare multi-statement? Come influisce questa scelta sulle prestazioni?

Risposta ed esempio:

  • La funzione INLINE (single-statement, restituisce subito un SELECT) viene ottimizzata come parte della query principale, non crea una tabella aggiuntiva e funziona più velocemente, il piano della query è comune.
  • La funzione multi-statement crea una tabella temporanea (variabile tabellare), il che generalmente porta a un piano di query peggiore, possibili errori di stima della cardinalità e calo delle prestazioni.
-- 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.