SQL Serverでスキーマ間を一括で移行する方法は?


8

現在、複数のデータベースがありますが、それらを組み合わせて、スキーマを使用してドメインコンテキストを分離したいと考えています。

MS SQL Server 2008 R2では、スキーマのすべてのコンテンツを一括して別のスキーマに再配置するにはどうすればよいですか?

たとえば、dboスキーマに作成したすべてのテーブル、ビュー、プロシージャ、インデックスなどは、スキーマに存在するようになりfooます。

編集:私はアーロンベルトランの素晴らしいコメントに基づいて明確にしたかったです。これはマルチテナンシーの状況ではありません。私たちの状況では、内部ツールプラグインが、テーブルをツールのデータベースにマージしなかった開発者によって分離して開発されました。


2
これは、FKと他の依存関係で本当にトリッキーになる可能性があります。なぜモデルを切り替えるのですか?さまざまな理由から、マルチスキーマモデルよりもマルチDBモデルが好きです。dba.stackexchange.com / questions
Aaron Bertrand

理由の中の@AaronBertrandは、別々のデータベース(たとえば、ユーザー自身のDB)にあるエンティティ間にリレーショナル依存関係があること、およびデータベースにまたがるビューがあり、したがってスキーマバインディングを使用できないことです。
マシュー


リレーションシップを保持するのに外部キーは必要ありません。これらは、他のさまざまな方法で明示的に適用できます。また、インデックスが作成されていない限り、ビューにSCHEMABINDINGを設定する必要はありません。私はそのようなシステムを13年間使用してきましたが、心配していることは、すべての人を単一のデータベースに結合することによって失うことと比較して、心配する価値がないと約束できます。
アーロンバートランド

@AaronBertrand私のユースケースとリンクでよく説明されている大きな違いは、これらのデータベースはクライアントやテナントをまったく分離しないことです。それらのそれぞれは、内部ツールの組み合わせによって使用されます。おそらく開発者は、メインDBに合流せずに取り付けられた真空工具プラグインを作成するので、彼らは分離されている理由です。私たちは、実際にはなります ...別のDBのテナントと異なる環境に対処する必要があります
マタイ

回答:


9

基本的なコンセプトは、実際には非常に簡単です:あなたは、スクリプトを生成sys.objectsし、sys.schemas構築することALTER SCHEMA TRANSFERのステートメントを。たとえば、dboスキーマに3つのオブジェクトがあり、それらすべてをblatスキーマに移動したいとします。

Table: dbo.foo
Table: dbo.bar
View:  dbo.vFooBar

次のコード:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'
  ALTER SCHEMA blat TRANSFER dbo.' + QUOTENAME(o.name) + ';'
FROM sys.objects AS o
INNER JOIN sys.schemas AS s
ON o.[schema_id] = s.[schema_id]
WHERE s.name = N'dbo';

PRINT @sql;
-- EXEC sp_executesql @sql;

このスクリプトを生成します(ただし、おそらくこの順序ではありません)。

ALTER SCHEMA blat TRANSFER dbo.bar;
ALTER SCHEMA blat TRANSFER dbo.foo;
ALTER SCHEMA blat TRANSFER dbo.vFooBar;

(追加のフィルターを追加して、移動したくないdboスキーマ内のオブジェクトを除外したり、特定のオブジェクトタイプを除外したりできます(たとえば、すべての関数がユーティリティ関数であり、移動する必要がない場合があります)。オブジェクトタイプなどで並べられたスクリプト)

ただし、すべてのオブジェクトを新しいスキーマに移動するには、いくつかの問題があります。

  1. おそらくあなたのコードはまだこれらのオブジェクトを参照しているでしょうdbo.object-力ずくでこれを修正する簡単な方法はありません。あなたは、おそらくの出現のすべて見つけることができdbo.、かなり簡単にしますが、これらはまた、偽陽性として、返すことができEXEC dbo.sp_executesqldbo.コメントの中には、中に残っているオブジェクトへの参照を真dbo.のスキーマなど

  2. あなたの依存関係はおそらく完全に無力ですが、私はこれを完全にテストしていません。私はこのシナリオでそれを知っています:

    CREATE SCHEMA blat AUTHORIZATION dbo;
    GO
    
    CREATE TABLE dbo.foo(a INT PRIMARY KEY);
    CREATE TABLE dbo.bar(a INT FOREIGN KEY REFERENCES dbo.foo(a));
    GO
    
    CREATE PROCEDURE dbo.pX AS
    BEGIN
      SET NOCOUNT ON;
      SELECT a FROM dbo.bar;
    END
    GO
    
    CREATE VIEW dbo.vFooBar
    AS
      SELECT foo.a, bar.a AS barA
        FROM dbo.foo 
        INNER JOIN dbo.bar
        ON foo.a = bar.a;
    GO
    
    ALTER SCHEMA blat TRANSFER dbo.foo;
    ALTER SCHEMA blat TRANSFER dbo.bar;
    ALTER SCHEMA blat TRANSFER dbo.pX;
    ALTER SCHEMA blat TRANSFER dbo.vFooBar;
    

    外部キーは実際には予想よりもスムーズに移行します(ただし、あなたよりも新しいバージョンでテストしていることに注意してください)。ただし、コードはblat.pXまだ参照しているためdbo.bar、明らかにプロシージャを実行します。

    EXEC blat.pX;

    このエラーが発生します:

    メッセージ208、レベル16、状態1、手順pX
    無効なオブジェクト名 'dbo.bar'。

    そして、次のような依存クエリ:

    SELECT * FROM sys.dm_sql_referenced_entities('blat.pX', N'OBJECT');

    このエラーが発生します:

    メッセージ2020、レベル16、状態1
    エンティティ「blat.pX」について報告される依存関係には、すべての列への参照が含まれていない場合があります。これは、エンティティが存在しないオブジェクトを参照しているか、エンティティ内の1つ以上のステートメントのエラーが原因です。クエリを再実行する前に、エンティティにエラーがないこと、およびエンティティによって参照されるすべてのオブジェクトが存在することを確認してください。

    そしてビューをクエリします:

    SELECT a, barA FROM blat.vFooBar;

    次のエラーが発生します:

    メッセージ208、レベル16、状態1、プロシージャvFooBar
    無効なオブジェクト名 'dbo.foo'。
    メッセージ4413、レベル16、状態1
    バインドエラーのため、ビューまたは関数 'blat.vFoobar'を使用できませんでした。

    したがって、これには多くのクリーンアップが含まれる可能性があります。また、すべてのオブジェクト参照を修正したら、すべてのモジュールを再コンパイルして、新しいスキーマのすべてのビューを更新する必要があります。上記の例とよく似たスクリプトを生成できます。


+1は、私は手動で削除する必要のようなそれはそういくつかの FKのこの転送を行うには...私はまだそれを原因かわからない
マシュー

@Matthewええ、外部キーが問題を引き起こしている場合は、この回答を参照してください。スクリプトの再作成部分が新しいスキーマを参照するように調整する必要があるだけです。
アーロンバートランド

@マシューあなたは、外部キーを持つ特定のテーブルがスムーズに転送されない状況が存在することを理解しましたか?あなたが得る正確なエラーメッセージは何ですか?制約を削除するのではなく単に無効にするだけでそれを回避できるかどうかを知るのは興味深いことですが、正確なブロッカーが何なのかわからないので、テストするのが難しいです。
アーロンバートランド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.