ダース以上のデータベースで使用されている関数があります。この関数に1回だけ書き込むことですべてのデータベースでアクセスできるようにしたいので、自分の関数に簡単にアクセスできるように、関数をマスターデータベースに書き込みます。
マスターデータベースにユーザー定義関数を書き込むことに問題はありますか?
インターネットをサーフィンするとき、一部は、関数をシステム関数に変換することを提案しました。 (「EXEC sp_ms_marksystemobject 'fn_db_name'」を使用)。
マスターデータベースで作成された関数をシステム関数に変換する必要はありますか?はいの場合、なぜですか?
私はジョナサンに同意します-関数が呼び出し元のデータベースコンテキストに基づいてローカルデータを返すことを想定していない限り、関数をユーティリティデータベースに配置します(これは、数値やカレンダーテーブル、関数の分割などを配置する場所でもあります) ):
USE UtilityDB;
GO
CREATE FUNCTION dbo.whatever() RETURNS ...
GO
次に、関数にアクセスする必要があるすべてのデータベースで、シノニムを作成します。
CREATE SYNONYM dbo.whatever() FOR UtilityDB.dbo.whatever();
このようにして、各データベースは、単純な2部構成の名前を使用して関数を参照できます。実際に存在する場所を知ったり、気にする必要はありません。そして、あなたは関数の単一のコピーを維持する必要があるだけです。
(そして実際、シノニムをmodel
データベースに入れて、新しいデータベースに自動的に作成されるようにすることができます。)
ユーザーオブジェクトをmaster
に配置することを嫌う理由-sp_spaceused
またはsp_helpindex
の独自にカスタマイズしたバージョンのように、呼び出し元のデータベースに対してグローバルに利用可能でコンテキストに依存する必要がない場合は、人々はmaster
でユーザーオブジェクトを探していないので、そこではあまり発見されません。また、master
に入力したユーザーのものも覚えておく必要があるため、ユーザーデータベースを他の場所に移行することが難しくなります。このためにユーティリティデータベースを作成または使用することにまったく夢中になっている場合は、msdb
が中央の場所のより実用的な選択だと思います。
@Jonathanと@Aaronは「ユーティリティ」データベースを使用することに同意しますが(私はUtility
と名付けます)、同義語の使用についてAaronに同意しますが、警告に注意を向けたいと思いますアーロンが重要であると述べた:
関数が呼び出し元のデータベースコンテキストに基づいてローカルデータを返すことが想定されていない限り...
つまり、doが「現在のデータベース」コンテキストを必要とする場合(実際に存在するデータベースで実行されているコードではなく、それがmaster
またはUtility
)の場合、master
以外を使用しても機能しません。
そして、データベースのコンテキストで実行する関数が必要な場合はfromと呼ばれ、関数を使用する計画はとにかく機能しませんドキュメント化されていない_sp_ms_marksystemobject
_システムストアドプロシージャを使用してマークしても、master
DBのコードはmaster
外の現在のデータベースコンテキストで実行できるため、ストアドプロシージャでのみ機能します。システムオブジェクトとしての関数。そして実際、関数の名前の前に_fn_
_または_sp_
_を付けても、オブジェクト名を完全に修飾しないと、それをマスターの外部で見つけることができません。そして、名前を完全に修飾しても、システムオブジェクトとしてマークされた後でも、master
データベースのコンテキストでのみ実行されます。
したがって、3つの選択肢があります。
Utility
データベースを使用し、関数を使用してUtility
データベースを指す必要があるデータベースで同義語を使用します。現在のDBコンテキストが必要な場合:
sp_
_で始まる名前に変更し、_sp_ms_marksystemobject
_システムストアドプロシージャを実行して、システムストアドプロシージャとしてマークします(それ以外の場合は、現在のDBコンテキストを反映しません) DB_NAME()
などの一部の組み込み関数の場合でも、クエリの場合)。私はこのアプローチの大ファンではありませんが、それはうまくいきます。SQLCLRを使用して、Utility
データベースに配置できる関数を作成し、現在のデータベース名(または任意のデータベース名)をその関数に渡して、送信されたクエリとなるダイナミックSQLの作成に使用します。 SQLCLRを使用してこのタイプを実行する例を、DBA.StackExchangeの次の回答にも投稿しました。
データベースコンテキストの呼び出しで実行する中央のストアドプロシージャ
このアプローチではシノニムを使用することもできます。その後、DB_NAME()
を渡しながら関数を呼び出すだけで、現在のデータベース名を自動的に渡すことができます。