In SQL, business logic can be implemented through User Defined Functions (UDF), which allows part of the calculations and business rules to be moved into the database.
Scalar functions return a single value and are called in expressions — for example, to calculate a total based on parameters:
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; -- Example usage: SELECT Name, dbo.GetDiscount(Price, LoyaltyLevel) AS DiscountPrice FROM Products;
Table-valued functions return a set of rows (a table):
CREATE FUNCTION dbo.ActiveOrders(@userId INT) RETURNS TABLE AS RETURN ( SELECT * FROM Orders WHERE UserId = @userId AND Status = 'Active' ); -- Usage: SELECT * FROM dbo.ActiveOrders(123);
Differences, limitations, and recommendations:
What is the difference between an INLINE table function and a multi-statement table function? How does this choice affect performance?
Answer and example:
-- 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 ... -- logic RETURN END
Case Study
Project: Financial Analytics.
We used scalar UDFs in the select part of a report query to a large array of tables: SELECT Amount, dbo.CalcTax(Amount, Type) FROM Transactions. The query took 5-10 minutes due to row-by-row processing of the UDF. We rewrote it using an embedded CASE: the time was reduced to seconds.
Case Study
Project: E-commerce. To find user carts, we used multi-statement table functions, where there was filtering logic over several steps. It turned out that SQL does not build an optimal plan and scans, even when a single element is needed. Replacing it with an INLINE function immediately sped up queries by 50 times.
Case Study
Project: CRM. We moved the business logic for bonus accrual into a complex UDF. After a couple of months, we realized that the business formulas had changed, and updating the function was complicated due to its tight coupling with the data. In an iterative product, the UDF led to high coordination costs for changes between the backend and the database.