パブリケーション データベースでのスキーマの変更
レプリケーションは、パブリッシュされたオブジェクトに対するさまざまなスキーマ変更をサポートしています。パブリッシュされた適切なオブジェクトに対して、以下に示すスキーマ変更を MicrosoftSQL Server パブリッシャで実行した場合、既定ではすべての SQL Server サブスクライバにその変更が反映されます。
ALTER TABLE
ALTER TABLE SET LOCK ESCALATION (スキーマ変更レプリケーションが有効で、トポロジに SQL Server 2005 または SQL Server Compact 3.5 サブスクライバが含まれている場合は使用しないでください) ALTER VIEW
ALTER PROCEDURE
ALTER FUNCTION
ALTER TRIGGER
データ定義言語 (DDL) トリガはレプリケートできないため、ALTER TRIGGER を使用できるのは、データ操作言語 (DML) トリガに対してのみです。
重要 |
---|
テーブルに対するスキーマ変更は、Transact-SQL または SQL Server 管理オブジェクト (SMO) を使用して行う必要があります。SQL Server Management Studio でスキーマ変更を行うと、Management Studio は、テーブルを削除して再作成しようとします。パブリッシュされたオブジェクトは削除できないため、スキーマ変更は失敗します。 |
トランザクション レプリケーションおよびマージ レプリケーションの場合、スキーマ変更はディストリビューション エージェントまたはマージ エージェントが実行されたときに、その増分が反映されます。スナップショット レプリケーションの場合、スキーマ変更は新しいスナップショットがサブスクライバで適用されるときに反映されます。スナップショット レプリケーションでは、同期が行われるたびにスキーマの新しいコピーがサブスクライバに送信されます。したがって、以前にパブリッシュされたオブジェクトに対するすべてのスキーマ変更 (上に列挙したもの以外も含む) は、同期のたびに自動的に反映されます。
パブリケーションのアーティクルの追加および削除については、「既存のパブリケーションへのアーティクルの追加および削除」を参照してください。
スキーマの変更をレプリケートするには
上に列挙したスキーマ変更は既定でレプリケートされます。スキーマ変更のレプリケートを無効にする方法については、以下のトピックを参照してください。
SQL Server Management Studio: スキーマの変更をレプリケートする方法 (SQL Server Management Studio)
レプリケーション Transact-SQL プログラミング : スキーマの変更をレプリケートする方法 (レプリケーション Transact-SQL プログラミング)
スキーマ変更に関する注意点
スキーマ変更をレプリケートする際には、以下の点に注意してください。
全般的な注意点
スキーマ変更は、Transact-SQL の制限の対象となります。たとえば、ALTER TABLE で主キー列を変更することはできません。
データ型マッピングは、初期スナップショットに対してのみ実行されます。スキーマ変更で、以前のバージョンのデータ型へのマッピングは行われません。たとえば、ALTER TABLE ADD datetime2 column というステートメントを SQL Server 2008 で使用している場合、SQL Server 2005 サブスクライバでは、データ型が nvarchar に変換されません。場合によっては、スキーマ変更がパブリッシャでブロックされます。
スキーマ変更の反映を許可するようにパブリケーションが設定されている場合は、関連するスキーマ オプションがパブリケーションのアーティクルに対してどのように設定されているかに関係なく、スキーマ変更が反映されます。たとえば、外部キー制約をレプリケートしないようにテーブル アーティクルに対して指定している場合に、外部キーをテーブルに追加する ALTER TABLE コマンドをパブリッシャで実行すると、サブスクライバで外部キーがテーブルに追加されます。これを回避するには、ALTER TABLE コマンドを実行する前にスキーマ変更の反映を無効にします。
スキーマ変更は、サブスクライバ (再パブリッシュ サブスクライバを含む) では行わず、パブリッシャでのみ行います。マージ レプリケーションについては、サブスクライバでスキーマを変更できないようになっています。トランザクション レプリケーションでは変更できますが、変更するとレプリケーションが失敗する可能性があります。
再パブリッシュ サブスクライバに反映された変更は、既定でそのサブスクライバに反映されます。
パブリッシャには存在するがサブスクライバには存在しないオブジェクトや制約を参照しているスキーマ変更は、パブリッシャでは成功しますが、サブスクライバでは失敗します。
外部キーを追加するときに参照されるサブスクライバのすべてのオブジェクトは、パブリッシャの対応するオブジェクトと名前と所有者が同じである必要があります。
インデックスの明示的な追加、削除、および変更はサポートされていません。制約 (主キー制約など) に対して暗黙的に作成されたインデックスはサポートされます。
レプリケーションによって管理されている ID 列の変更や削除はサポートされていません。ID 列の自動管理の詳細については、「ID 列のレプリケート」を参照してください。
非決定的関数を含むスキーマ変更はサポートされていません。これは、パブリッシャとサブスクライバのデータが異なる結果になる可能性があるためです (この状態を "未集約" と言います)。たとえば、ALTER TABLE SalesOrderDetail ADD OrderDate DATETIME DEFAULT GETDATE() というコマンドをパブリッシャで実行した場合、このコマンドがサブスクライバにレプリケートされて実行されると異なる値になります。非決定的関数の詳細については、「決定的関数と非決定的関数」を参照してください。
制約には明示的に名前を付けることをお勧めします。明示的に制約に名前を付けない場合、SQL Server が制約の名前を生成するので、これらの名前がパブリッシャと各サブスクライバで異なります。このことが原因で、スキーマ変更のレプリケーション中に問題が発生することがあります。たとえば、パブリッシャ側で列を削除することにより依存制約が削除されると、レプリケーションは、サブスクライバ側でこの制約を削除しようとします。制約の名前が異なるので、サブスクライバでの削除は失敗します。制約の名前付けの問題によって同期に失敗する場合、サブスクライバ側で制約を手動で削除して、マージ エージェントを再実行してください。
テーブルをレプリケーション用にパブリッシュする場合、パブリケーション スナップショットが既に生成されている場合は、そのテーブルの列を XML のデータ型に変更することはできません。列を変更するには、まずレプリケーションを削除する必要があります。詳細については、「レプリケーションの削除」を参照してください。
列の追加
テーブルに新しい列を追加し、その列を既存のパブリケーションに含めるには、ALTER TABLE <Table> ADD <Column> を実行します。この列は、既定ですべてのサブスクライバにレプリケートされます。この列では、NULL 値を許容するか既定の制約を含める必要があります。列の追加の詳細については、このトピックの「マージ レプリケーション」を参照してください。
テーブルに新しい列を追加し、その列を既存のパブリケーションに含めない場合は、スキーマ変更のレプリケーションを無効にしてから、ALTER TABLE <Table> ADD <Column> を実行します。
既存のパブリケーションに既存の列を含めるには、sp_articlecolumn (Transact-SQL)、sp_mergearticlecolumn (Transact-SQL)、または [パブリケーションのプロパティ - <Publication>] ダイアログ ボックスを使用します。
詳細については、「列フィルタを定義および変更する方法 (レプリケーション Transact-SQL プログラミング)」および「列フィルタを定義および変更する方法 (SQL Server Management Studio)」を参照してください。この場合は、サブスクリプションの再初期化が必要になります。
パブリッシュされたテーブルに ID 列を追加することはサポートされていません。これは、列がサブスクライバにレプリケートされると集約されなくなる可能性があるからです。パブリッシャの ID 列の値は、影響を受けるテーブルの行が物理的に格納されている順序に依存します。サブスクライバで行が同じように格納されているとは限らないため、同じ行で ID 列の値が異なる可能性があります。
列の削除
既存のパブリケーションから列を削除し、その列をパブリッシャのテーブルから削除するには、ALTER TABLE <Table> DROP <Column> を実行します。この列は、既定ですべてのサブスクライバのテーブルから削除されます。
既存のパブリケーションから列を削除し、その列をパブリッシャのテーブルからは削除しない場合は、sp_articlecolumn (Transact-SQL)、sp_mergearticlecolumn (Transact-SQL)、または [パブリケーションのプロパティ - <Publication>] ダイアログ ボックスを使用します。
詳細については、「列フィルタを定義および変更する方法 (レプリケーション Transact-SQL プログラミング)」および「列フィルタを定義および変更する方法 (SQL Server Management Studio)」を参照してください。この場合は、新しいスナップショットの生成が必要になります。
削除する列は、データベースのどのパブリケーションのどのアーティクルのフィルタ句でも使用できません。
パブリッシュされたアーティクルから列を削除するときには、データベースに影響する可能性のある列の制約、インデックスまたはプロパティについて考慮する必要があります。次に例を示します。
主キーで使用されている列をトランザクション パブリケーションのアーティクルから削除することはできません。それらの列は、レプリケーションによって使用されます。
マージ パブリケーションのアーティクルから rowguid 列を削除したり、更新サブスクリプションをサポートしているトランザクション パブリケーションのアーティクルから mstran_repl_version 列を削除することはできません。それらの列は、レプリケーションによって使用されます。
インデックスの変更は、サブスクライバに反映されません。パブリッシャ側で列を削除することにより依存インデックスが削除されても、インデックスの削除はレプリケートされません。パブリッシャ側で列を削除する前に、サブスクライバ側でインデックスを削除する必要があります。この操作を行っておくと、列をパブリッシャからサブスクライバにレプリケートするときに列の削除に成功します。サブスクライバ側のインデックスが原因で同期に失敗する場合、手動でインデックスを削除して、マージ エージェントを再実行してください。
制約は、削除が可能になるように明示的に名前を付ける必要があります。詳細については、このトピックの「全般的な注意点」を参照してください。
トランザクション レプリケーション
スキーマ変更は、以前のバージョンの SQL Server を実行しているサブスクライバにも反映されますが、DDL ステートメントに含まれているすべての構文が、サブスクライバで実行されているバージョンでサポートされている必要があります。
サブスクライバがデータを再パブリッシュする場合にサポートされるスキーマ変更は、列の追加と削除のみです。これらの変更は、ALTER TABLE DDL 構文ではなく sp_repladdcolumn (Transact-SQL) と sp_repldropcolumn (Transact-SQL) を使用して、パブリッシャで行う必要があります。
スキーマ変更は、SQL Server 以外のサブスクライバには反映されません。
スキーマ変更は、SQL Server 以外のパブリッシャからは反映されません。
テーブルとしてレプリケートされたインデックス付きビューを変更することはできません。インデックス付きビューとしてレプリケートされたインデックス付きビューは変更できますが、変更すると、インデックス付きビューではなく通常のビューになります。
パブリケーションが即時更新サブスクリプションやキュー更新サブスクリプションをサポートしている場合は、スキーマ変更を行う前にシステムを停止する (パブリッシュされたテーブルのすべての操作をパブリッシャとサブスクライバで停止して、保留中のデータ変更をすべてのノードに反映する) 必要があります。スキーマ変更がすべてのノードに反映されたら、パブリッシュされたテーブルの操作を再開できます。
パブリケーションがピア ツー ピア トポロジにある場合は、スキーマ変更を行う前にシステムを停止する必要があります。詳細については、「レプリケーション トポロジを停止する方法 (レプリケーション Transact-SQL プログラミング)」を参照してください。
テーブルに timestamp 列を追加して、timestamp を binary(8) にマップすると、すべてのアクティブなサブスクリプションでアーティクルが再初期化されます。
マージ レプリケーション
マージ レプリケーションでスキーマ変更がどのように処理されるかは、パブリケーションの互換性レベルと、スナップショットがネイティブ モード (既定) とキャラクタ モードのどちらに設定されているかによって決まります。
スキーマ変更をレプリケートするには、パブリケーションの互換性レベルが少なくとも 90RTM である必要があります。サブスクライバが以前のバージョンの SQL Server を実行している場合や、互換性レベルが 90RTM 未満の場合でも、sp_repladdcolumn (Transact-SQL) や sp_repldropcolumn (Transact-SQL) を使用して列の追加や削除を行うことができます。ただし、これらのプロシージャは非推奨です。
SQL Server 2008 で導入されたデータ型の列を既存のアーティクルに追加すると、SQL Server は次のように動作します。
100RTM、ネイティブ モードのスナップショット
100RTM、キャラクタ モードのスナップショット
その他すべての互換性レベル
hierarchyid
変更を許可する
変更をブロックする
変更をブロックする
geography および geometry
変更を許可する
変更を許可する1
変更をブロックする
filestream
変更を許可する
変更をブロックする
変更をブロックする
date、time、datetime2、および datetimeoffset
変更を許可する
変更を許可する1
変更をブロックする
1 SQL Server Compact サブスクライバは、これらのデータ型をサブスクライバ側で変換します。
パブリケーションの互換性の詳細については、「レプリケーション トポロジにおける複数バージョンの SQL Server の使用」の「マージ パブリケーションの互換性レベル」を参照してください。
スキーマ変更の適用時にエラー (サブスクライバで利用できないテーブルを参照する外部キーを追加した結果のエラーなど) が発生すると、同期が失敗し、サブスクリプションを再初期化しなければならなくなります。
結合フィルタやパラメータ化されたフィルタに含まれている列に対してスキーマ変更を行う場合は、すべてのサブスクリプションを再初期化し、スナップショットを再生成する必要があります。
マージ レプリケーションには、トラブルシューティングの際にスキーマ変更をスキップするストアド プロシージャが用意されています。詳細については、「sp_markpendingschemachange (Transact-SQL)」および「sp_enumeratependingschemachanges (Transact-SQL)」を参照してください。