web-dev-qa-db-ja.com

ストアドプロシージャコードを動的SQLなしで他のデータベースを動的に参照させる方法はありますか?

2つのデータベースがある状況があります。

  • ABCData
  • ABCUsers

ABCDataのストアドプロシージャの1つは、ABCUsersのテーブルへの挿入を実行する必要があります。これは単にハードコーディングすることができます:

INSERT ABCUsers.dbo.Table1 VALUES('a');

しかし次に遭遇する問題は、テストと開発の目的で、これらのデータベースのペアを同様の名前が付けられた他のデータベースにバックアップおよび再展開することです。

  • XYZData
  • XYZUsers

つまり、XYZDataデータベースには、機能しないsprocが含まれます-挿入にはハードコードされたABCUsers.dbo.Table1があり、それを変更したくありません

Sprocで現在のデータベース名を見つけて調整し、SQLを動的に実行できます。

DECLARE @DataDbName sysname = (DB_NAME());
DECLARE @UserDBName NVARCHAR(20) = (SELECT REPLACE(@DataDbName, 'Data', 'Users'));
EXEC CONCAT('INSERT ', @UserDbName, '.dbo.Table1 VALUES(''a'');')

しかし、そうする見込みがあると、実際に体調が悪くなると思います;)(特に、これは数十のsprocが他のデータベースに数十の呼び出しを行う非常に単純化された例であるためです)

作成中にデータベース名にエイリアスを付ける方法はありますか?したがって、sprocは常に次のように言うことができます:

INSERT UserDbAlias.dbo.Table1 VALUES('a');

そしてABCUsersデータベースが作成されるとUserDbAlias -> ABCUsersが、XYZUsers dbが作成されるとUserDbAlias -> XYZUsers


または、これはgit/tfsソース管理です。sprocのソース管理バージョンを記述して、デプロイ時に動的に変更されるようにする方法があります。元のソースには、db名のプレースホルダーの種類を含めることができますが、デプロイ時に実際にハードコードされたさまざまなdb名に置き換えられます(自動的に)


脚注:私は 名前をハードコーディングせずに他のDBを参照する方法 を見ましたが、これは私の問題を説明しているように見えますが、答えはありません。その質問は「同義語を見てきましたが、EF6でうまくいかないでしょう」と述べました(言い換え)

類義語はうまくいくでしょうか? EF6を使用していますが、なぜうまくいかないのかという点で、実際の問題は何なのかわかりません。 db内のsproc名は変更されません。また、sproc自体にエイリアスを設定する必要はありません。エイリアスに必要な挿入テーブル名です。 sprocがABCDataXYZDataのどちらにあるかに関係なく常にSproc1と呼ばれ、シノニムの解決がsproc内で発生する場合、EF6でも問題が発生しますか?

3
Caius Jard

コメントで提起された設計上の考慮事項は別として、...

ストアドプロシージャを作成する前に、1レベルの間接参照を検討してください。

  • スキーマ名のトークンプレースホルダーを使用して、ストアドプロシージャのテンプレートを記述します

INSERT DBNAMETOKEN.dbo.Table1 VALUES('a');

  • トークンを実際のスキーマ名に置き換えて、スキーマごとに新しいファイルを作成するデプロイ前スクリプト(sed?)を記述します。
  • 結果のスクリプトをスキーマごとの展開ディレクトリに配置し、そこから通常どおりにインストールできます。

利点

  • うまくスケーリング
  • テンプレートバージョンとカスタムバージョンの両方がバージョン管理下にある可能性があります
  • 更新/修正は、テンプレートファイルへの単一の変更を通じて引き続きデプロイされ、ビルドステップを通じて伝播される場合があります
  • 状況に応じて、各スキーマへの更新の展開をスケジュール/追跡するのがおそらく簡単になる
  • ストアドプロシージャを、異なるスキーマ間で機能させるダイナミクスではなく、手元のタスクに焦点を合わせた単純なSQLセットに縮小します。
0
Cary Reams