パブリケーション データベースでのスキーマの変更

レプリケーションは、パブリッシュされたオブジェクトに対するさまざまなスキーマ変更をサポートしています。パブリッシュされた適切なオブジェクトに対して、以下に示すスキーマ変更を Microsoft SQL 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 は、テーブルを削除して再作成しようとします。パブリッシュされたオブジェクトは削除できないため、スキーマ変更は失敗します。

トランザクション レプリケーションおよびマージ レプリケーションの場合、スキーマ変更はディストリビューション エージェントまたはマージ エージェントが実行されたときに、その増分が反映されます。スナップショット レプリケーションの場合、スキーマ変更は新しいスナップショットがサブスクライバーで適用されるときに反映されます。スナップショット レプリケーションでは、同期が行われるたびにスキーマの新しいコピーがサブスクライバーに送信されます。したがって、以前にパブリッシュされたオブジェクトに対するすべてのスキーマ変更 (上に列挙したもの以外も含む) は、同期のたびに自動的に反映されます。

パブリケーションのアーティクルの追加および削除については、「既存のパブリケーションへのアーティクルの追加および削除」を参照してください。

スキーマの変更をレプリケートするには

上に列挙したスキーマ変更は既定でレプリケートされます。スキーマ変更のレプリケートを無効にする方法については、以下のトピックを参照してください。

スキーマ変更に関する注意点

スキーマ変更をレプリケートする際には、以下の点に注意してください。

全般的な注意点

  • スキーマ変更は、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 のデータ型に変更することはできません。列を変更するには、まずレプリケーションを削除する必要があります。詳細については、「レプリケーションの削除」を参照してください。

  • READ UNCOMMITTED は、パブリッシュされたテーブルで DDL を実行するときにサポートされない分離レベルです。

列の追加

  • テーブルに新しい列を追加し、その列を既存のパブリケーションに含めるには、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 以外のサブスクライバーにはレプリケートされません。

  • スキーマ変更は、SQL Server 以外のパブリッシャーからは反映されません。

  • テーブルとしてレプリケートされたインデックス付きビューを変更することはできません。インデックス付きビューとしてレプリケートされたインデックス付きビューは変更できますが、変更すると、インデックス付きビューではなく通常のビューになります。

  • パブリケーションが即時更新サブスクリプションやキュー更新サブスクリプションをサポートしている場合は、スキーマ変更を行う前にシステムを停止する (パブリッシュされたテーブルのすべての操作をパブリッシャーとサブスクライバーで停止して、保留中のデータ変更をすべてのノードに反映する) 必要があります。スキーマ変更がすべてのノードに反映されたら、パブリッシュされたテーブルの操作を再開できます。

  • 以前のエディションの SQL Server では、スキーマ変更を行う前に、ピア ツー ピア トポロジにあるパブリケーションを停止する必要がありました。SQL Server 2008 以降では、このセクションで別途説明されている場合を除き、パブリケーションを停止する必要はなくなりました。

  • テーブルに 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)」を参照してください。

変更履歴

変更内容

「トランザクション レプリケーション」の注意点に、スキーマ変更のたびにピア ツー ピア トポロジを停止する必要はないという説明を追加しました。