Programmingバックエンド開発者

SQLでユーザー定義関数(UDF)を使用して複雑なビジネスルールや計算を実装するにはどうすればよいですか?スカラーUDFとテーブルUDFの違いと制限は何ですか?どのような場合にそれらを使用するのが適切で、どのような場合に外部アプリケーションで同様のロジックを実装する方が良いですか?

Hintsage AIアシスタントで面接を突破

回答。

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);

違い、制限、推奨事項:

  • スカラーUDFは、大きな選択肢ではパフォーマンスが低下しがちで、行ごとに呼び出されるためです;
  • テーブルUDFはクエリプランにうまく統合され、通常のテーブルとしての使用が可能です;
  • 外部リソースへのアクセスが必要なロジックや複雑なビジネス処理は、SQLの外に持ち出すのが望ましいです。

ひねりの効いた質問。

INLINEテーブル関数とマルチステートメントテーブル関数の違いは何ですか?この選択はパフォーマンスにどのように影響しますか?

回答と例:

  • INLINE関数(単一のステートメントで、すぐにSELECTを返す)は、メインクエリの一部として最適化され、追加のテーブルを作成せずに、より速く動作し、クエリプランは共通です。
  • マルチステートメント関数は、一時テーブル(テーブル変数)を作成し、そのため通常はクエリプランが悪化し、カーディナリティの評価エラーが発生したり、パフォーマンスが低下します。
-- INLINE 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に書き直したところ、時間が数秒に短縮されました。


歴史

プロジェクト: Eコマース。 ユーザーのショッピングカートを検索するために、複数の段階のフィルタリングロジックを持つマルチステートメントテーブル関数を使用しました。SQLが最適なプランを構築せず、必要な要素でさえスキャンを実行していました。INLINE関数に置き換えたところ、クエリの速度が50倍向上しました。


歴史

プロジェクト: CRM。 ボーナス計算のビジネスロジックを複雑なUDFに移行しました。数か月後、ビジネスの計算式が変更され、データとの厳密な結びつきのために関数の更新が難しいことが判明しました。反復的な製品ではUDFがバックエンドとDB間の変更協調に高いコストをもたらしました。