データベース側にロジックを保持することは、ほとんどの場合正しいことです。
質問で述べたように、ほとんどのビジネス ルールには非常に単純なロジックが含まれますが、通常は膨大な量のデータを処理します。
データベース エンジンはそのロジックを実装するのに適しています。なぜなら、データベース エンジンはデータI/O
を最小限に抑え、データベースはほとんどのデータ変換をはるかに効率的に実行するからです。
しばらく前に、このトピックについて非常に主観的なブログ投稿を書きました。
補足: aUDF
はストアド プロシージャと同じではありません。
AUDF
は、クエリ内で callable によって設計された関数であるため、可能な操作の非常に限られたサブセットしか実行できません。
ストアド プロシージャを使用すると、さらに多くのことができます。
アップデート:
あなたが示した例では、「派生フィールド」を計算するロジックを変更するなどUDF
、フィールドを計算するのは問題ありません。
しかし、(念のため) パフォーマンスが問題になる場合 (そして、私が信じているように、これは考えられるよりもはるかに早い時期です)、セットベースの操作でデータを変換する方が、s を使用するよりもはるかに効率的である可能性がありますUDF
。
UDF
この場合、 s (レコードベース) の更新に制限するのではなく、より効率的なクエリを含む結果セットを返すビュー、ストアド プロシージャ、またはテーブル値関数を作成することができます。
1 つの例: クエリに「ユーザー スコア」のようなものがあり、変更される可能性があると感じ、それを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
、これにより、結果セットの構造を維持し、ロジックをプレゼンテーションから分離しながら、エンジンに最適化のためのより広いスペースを与えることができます。