SQL Server では、関数は、厳密に決定的、決定的、または非決定的に分類されます。
一連の特定の入力値に対して関数が常に同じ結果を返す場合、関数は厳密に決定的です。
ユーザー定義関数では、決定性に少数の固定概念が適用されます。一連の特定の入力値やデータベース状態に対して関数が常に同じ結果を返す場合、ユーザー定義関数は決定的です。関数が厳密に決定的でなく、その関数がデータ アクセスの場合、この意味では決定的になります。
非決定的関数は、一連の同じ入力値で繰り返し呼び出されたときに、さまざまな結果を返すことがあります。たとえば、関数 GETDATE() は非決定的です。SQL Server では、非決定性のさまざまなクラスに制限が課せられます。したがって、非決定的関数は、注意深く使用する必要があります。
組み込み関数の場合は、決定性と厳密な決定性は同じです。Transact-SQL ユーザー定義関数の場合は、システムによって定義が確認され、非決定的関数を定義できないようになっています。ただし、データ アクセス関数または非スキーマ バインド関数は、厳密に決定的ではないと見なされます。共通言語ランタイム (CLR) 関数の場合は、関数の決定性、データ アクセス、およびシステム データ アクセスのプロパティが関数の定義によって指定されますが、これらのプロパティはシステムでは確認されないので、常に、厳密に決定的ではないと見なされます。
関数の決定性が明確でない場合は、使用できる場所が制限されることがあります。インデックス付きビュー、インデックス付き計算列、保存される計算列、または Transact-SQL ユーザー定義関数の定義では、決定的関数のみを呼び出すことができます。
関数の厳密な決定性が明確でない場合は、貴重なパフォーマンスの最適化がブロックされることがあります。内部的に正確さを保つために手順を並べ替える特定のプランがスキップされます。また、ユーザー定義関数への呼び出しの数、順序、およびタイミングは、実装によって異なります。これらの呼び出しのセマンティックに依存しないでください。ランタイム定数の非決定的組み込みの RAND、および GETDATE ファミリのほかに、呼び出しの数、順序、およびタイミングは選択したプランによって異なります。
ベスト プラクティスと推奨事項
可能な場合は、以下のガイドラインに従うことをお勧めします。
1.選択可能な場合は、厳密に決定的な関数を記述します。特に、Transact-SQL 関数はスキーマ バインドにします。
2.非決定的な関数の使用を選択リストの一番外側に検定します。
3.パフォーマンスが重要なクエリでは、非決定的関数を使用しないでください。
4.呼び出しの数、順序、またはタイミングは実装によって異なるので、これらに依存しないでください。
詳細については、「決定的関数と非決定的関数」を参照してください。