将逻辑保留在数据库端几乎总是正确的做法。
正如您在问题中提到的,大多数业务规则都涉及非常简单的逻辑,但它通常处理大量数据。
数据库引擎是实现该逻辑的正确选择,因为首先,它将数据保持I/O
在最低限度,其次,数据库执行大多数数据转换的效率更高。
前段时间我就这个话题写了一篇非常主观的博文:
附带说明: aUDF
与存储过程不同。
AUDF
是一个在查询中由 callable 设计的函数,因此它只能执行非常有限的可能操作子集。
你可以做的更多是存储过程。
更新:
在您给出的示例中,就像更改计算“派生字段”的逻辑一样UDF
,计算该字段是可以的。
但是(以防万一)当性能成为问题时(相信我,这会比人们想象的要快得多),使用基于集合的操作转换数据可能比使用UDF
s.
在这种情况下,您可能希望创建一个视图、一个存储过程或一个表值函数返回一个结果集,该结果集将包含更有效的查询,而不是限制自己更新UDF
s(它们是基于记录的)。
一个例子:您的查询有类似“用户分数”之类的东西,您觉得可能会发生变化并将其包装成UDF
SELECT user_id, fn_getUserScore(user_id)
FROM users
最初,这只是表中的一个普通字段:
CREATE FUNCTION fn_getUserScore(@user_id INT) RETURNS INT
AS
BEGIN
DECLARE @ret INT
SELECT user_score
INTO @ret
FROM users
WHERE user_id = @user_id
RETURN @ret
END
,然后您决定使用其他表中的数据来计算它:
CREATE FUNCTION fn_getUserScore(@user_id INT) RETURNS INT
AS
BEGIN
DECLARE @ret INT
SELECT SUM(vote)
INTO @ret
FROM user_votes
WHERE user_id = @user_id
RETURN @ret
END
这将使引擎NESTED LOOPS
在任何一种情况下都使用效率最低的算法。
但是,如果您创建了一个视图并像这样重写了基础查询:
SELECT user_id, user_score
FROM users
SELECT user_id, SUM(vote) AS user_score
FROM users u
LEFT JOIN
user_votes uv
ON uv.user_id = u.user_id
,这将为引擎提供更广阔的优化空间,同时仍保持结果集结构并将逻辑与表示分离。