在SQL中,可以通过用户定义函数(User Defined Functions, UDF)实现业务逻辑,这允许将部分计算和业务规则转移到数据库中。
标量函数返回单一值,并在表达式中被调用,例如,根据参数计算折扣:
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; -- 使用示例: SELECT Name, dbo.GetDiscount(Price, LoyaltyLevel) AS DiscountPrice FROM Products;
表格函数返回一组行(表):
CREATE FUNCTION dbo.ActiveOrders(@userId INT) RETURNS TABLE AS RETURN ( SELECT * FROM Orders WHERE UserId = @userId AND Status = 'Active' ); -- 使用: SELECT * FROM dbo.ActiveOrders(123);
区别、限制和建议:
内联表格函数和多语句表格函数之间有什么区别?这种选择如何影响性能?
答案和示例:
-- 内联 CREATE FUNCTION dbo.InlineActiveOrders(@userId INT) RETURNS TABLE AS RETURN ( SELECT * FROM Orders WHERE UserId = @userId AND Status = 'Active' ); -- 多语句 CREATE FUNCTION dbo.MultiActiveOrders(@userId INT) RETURNS @result TABLE (...) AS BEGIN INSERT INTO @result SELECT ... -- 逻辑 RETURN END
故事
项目:金融分析。
在对大规模表的报告查询的select部分中使用了标量UDF:SELECT Amount, dbo.CalcTax(Amount, Type) FROM Transactions。由于逐行处理UDF,该查询执行时间为5-10分钟。重写为内置CASE后,时间降至秒。
故事
项目:电子商务。 在查找用户购物车时使用了多语句表格函数,其中有多个阶段的过滤逻辑。结果发现SQL没有构建最佳计划并进行扫描,即使只需一个元素。替换为内联函数后,查询速度立即提高了50倍。
故事
项目:CRM。 将奖金计算的业务逻辑提取到复杂的UDF中。几个月后意识到商业公式变更,但由于与数据的紧密耦合,更新函数变得困难。在迭代产品中,UDF导致了后端与数据库之间协调变更的高成本。