2つのデータベース間に外部キー関係を追加する


90

2つの異なるデータベースに2つのテーブルがあります。table1(database1)には、column1という列があり、これが主キーです。table2(database2)にcolumn2という列があり、それを外部キーとして追加したいと思います。

追加しようとすると、次のエラーが発生しました。

メッセージ1763、レベル16、状態0、行1
データベース間の外部キー参照はサポートされていません。外部キーDatabase2.table2。

メッセージ1750、レベル16、状態0、行1
制約を作成できませんでした。以前のエラーを参照してください。

テーブルは異なるデータベースにあるので、どうすればよいですか。

回答:


84

トリガーを使用して、データベース全体の参照制約を管理する必要があります。


基本的に、挿入、更新トリガーを作成して、主キーテーブルにキーが存在することを確認します。キーが存在しない場合は、挿入または更新を元に戻してから、例外を処理します。

例:

Create Trigger dbo.MyTableTrigger ON dbo.MyTable, After Insert, Update
As
Begin

   If NOT Exists(select PK from OtherDB.dbo.TableName where PK in (Select FK from inserted) BEGIN
      -- Handle the Referential Error Here
   END

END

編集: 明確にするために。これは、参照整合性を適用するための最良のアプローチではありません。理想的には、両方のテーブルを同じデータベースに配置する必要がありますが、それが不可能な場合は。次に、上記はあなたのための潜在的な回避策です。


3
@John Hartsock-上記の例は、適切なトランザクション処理を追加しないと、簡単に失敗する可能性があります。-で発生する可能性がある問題のタイプのまともな議論ここで見つけることができます「)(存在しない場合はその後の挿入」stackoverflow.com/questions/108403/...
EBarr

16
@John Hartsock-ソリューションには抜け穴があります。2つのデータベースのいずれかがバックアップから復元された場合、もちろんトリガーは起動しません。これが、孤立した行になってしまう方法です。
AK

4
@AlexKuznetsovその通り。私が説明したように、これは最善のアプローチではありませんが、潜在的な回避策です。
John Hartsock 2011年

2
これは私がちょうどトリガについて考えおろか...彼はこのような何かを求めているということだけで事実は、彼が最も可能性が高い何かを間違ってやっているという症状ですOPの実現を願っています...だけので間違っている...
MeTitus

1
@Marco私の回答に投稿したとおり「明確にするために。これは参照整合性を適用するための最良のアプローチではありません。理想的には両方のテーブルを同じデータベースに配置する必要がありますが、それが不可能な場合は、上記の回避策が考えられます。君は。" これはおそらく良い考えではないと説明しました。
ジョン・ハートソック2014年

48

堅実な整合性が必要な場合は、両方のテーブルを1つのデータベースに配置し、FK制約を使用します。親テーブルが別のデータベースにある場合、古いバックアップからその親データベースを復元することを妨げるものは何もないため、孤立します。

これが、データベース間のFKがサポートされていない理由です。


27

私の経験では、関連する2つのテーブルの主要な信頼できる情報ソースが2つの別々のデータベースにある必要がある場合にこれを処理する最良の方法は、テーブルのコピーをプライマリロケーションからセカンダリロケーションに同期することです(T-を使用)適切なエラーチェックを備えたSQLまたはSSIS-外部キー参照がある間はテーブルを切り捨てて再入力できないため、テーブルの更新で猫のスキンを作成する方法がいくつかあります)。

次に、2番目の場所にある従来のFK関係をテーブルに追加します。これは、事実上読み取り専用のコピーです。

プライマリロケーションでトリガーまたはスケジュールされたジョブを使用して、コピーを最新の状態に保つことができます。


1
再。「プライマリロケーションでジョブをトリガーまたはスケジュールして、コピーを最新の状態に保つことができます」:SQL Serverレプリケーション(具体的には、サブスクライバーのコピー(外部キー制約が必要なテーブルを持つコピー)以降のトランザクションタイプとマージタイプ)だけを使用しないのはなぜですか読み取り専用にする必要があります)?参照:リンク
トム

@Tomはい、確かにレプリケーションを使用して、リモートデータベースでテーブルのコピーを更新しておくことができます。
ケイドルー2017

20

ユーザー定義関数でチェック制約を使用してチェックを行うことができます。トリガーよりも信頼性があります。外部キーと同じように、必要に応じて無効化および再有効化でき、database2の復元後に再チェックできます。

CREATE FUNCTION dbo.fn_db2_schema2_tb_A
(@column1 INT) 
RETURNS BIT
AS
BEGIN
    DECLARE @exists bit = 0
    IF EXISTS (
      SELECT TOP 1 1 FROM DB2.SCHEMA2.tb_A 
      WHERE COLUMN_KEY_1 =  @COLUMN1
    ) BEGIN 
         SET @exists = 1 
      END;
      RETURN @exists
END
GO

ALTER TABLE db1.schema1.tb_S
  ADD CONSTRAINT CHK_S_key_col1_in_db2_schema2_tb_A
    CHECK(dbo.fn_db2_schema2_tb_A(key_col1) = 1)

1
これは受け入れ答えよりもよりよい解決策であり、あなたはまた、複数のテーブルの上にそれを再利用することができます
Milox

3

簡単に言うと、SQL Server(SQL 2008以降)は、エラーメッセージに示されているように、データベース間の外部キーをサポートしていません。

宣言型の参照整合性(FK)を持つことはできませんが、トリガーを使用して同じ目標を達成できます。作成するロジックにバグがある可能性があるため、信頼性は少し低くなりますが、同じように到達できます。

SQLドキュメント@http ://msdn.microsoft.com/en-us/library/aa258254%28v=sql.80%29.aspxを参照してください。どの状態:

トリガーは、ビジネスルールとデータの整合性を強化するためによく使用されます。SQL Serverは、テーブル作成ステートメント(ALTERTABLEおよびCREATETABLE)を介して宣言型参照整合性(DRI)を提供します。ただし、DRIはデータベース間の参照整合性を提供しません。参照整合性(テーブルの主キーと外部キー間の関係に関するルール)を適用するには、主キーと外部キーの制約(ALTERTABLEとCREATETABLEのPRIMARYKEYキーワードとFOREIGNKEYキーワード)を使用します。トリガーテーブルに制約が存在する場合、それらはINSTEADOFトリガー実行後およびAFTERトリガー実行前にチェックされます。制約に違反した場合、INSTEAD OFトリガーアクションはロールバックされ、AFTERトリガーは実行(起動)されません。

SQLTeamでもOKの議論があります-http //www.sqlteam.com/forums/topic.asp?TOPIC_ID = 31135


0

エラーメッセージが示すように、これはSQLサーバーではサポートされていません。参照の整合性を確保する唯一の方法は、トリガーを使用することです。


1
例を挙げて説明していただけますか
Sam
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.