保持數據庫端的邏輯幾乎總是正確的。
正如你在你的問題中提到,大多數業務規則涉及很簡單的邏輯,但它通常以大量的數據交易。
數據庫引擎是實現該邏輯的正確方法,因爲它首先使數據保持最小,其次,數據庫更有效地執行大多數數據轉換。
前一段時間我寫了一個非常主觀的博客中對這個話題:
一個側面說明:一UDF
是不一樣的存儲過程。
A UDF
是一個由查詢內部可調用的函數設計的函數,因此它只能執行一個非常有限的可能操作子集。
你可以做更多的是存儲過程。
更新:
在你給了,比如改變計算「派生出來的字段」邏輯的例子中,計算領域是OK的UDF
。
但是(爲了以防萬一)當性能會成爲一個問題(並相信我,這可能會更快,人們可能會認爲),使用基於集合的操作來轉換數據可能會比使用UDF
s更有效。
在這種情況下,您可能希望創建一個視圖,存儲過程或表值函數返回一個結果集,其中將包含寧可把自己侷限於更新UDF
個更高效的查詢(這是基於記錄的) 。
一個例子:查詢有類似的東西,你覺得會隨時更改,並將其包裝成一個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
,這將給引擎優化更廣泛的空間,同時仍保持結果集的結構和表現分離的邏輯。
謝謝大家!看起來這種方法應該是OK :)同樣,性能不是問題,因爲它們僅在每個ETL /快照實例中使用一次。因此,填充這些函數輸出到的字段可能需要一兩分鐘或三天的時間,但在此之後,有人會始終只對表進行查詢,而不會使用查詢中的函數。那麼,至少他們不應該使用它們! – chucknelson 2010-01-28 23:44:37