web-dev-qa-db-fra.com

Ajouter une relation de clé étrangère entre deux bases de données

J'ai deux tables dans deux bases de données différentes. Dans table1 (dans la base de données1), il existe une colonne appelée colonne1 et il s'agit d'une clé primaire. Maintenant, dans table2 (dans la base de données2), il existe une colonne appelée colonne2 et je veux l'ajouter en tant que clé étrangère.

J'ai essayé de l'ajouter et cela m'a donné l'erreur suivante:

Msg 1763, niveau 16, état 0, ligne 1
Les références de clé étrangère inter-bases de données ne sont pas prises en charge. Clé étrangère Database2.table2.

Msg 1750, niveau 16, état 0, ligne 1
Impossible de créer une contrainte. Voir les erreurs précédentes.

Comment puis-je faire cela puisque les tables sont dans différentes bases de données.

69
Sam

Vous devez gérer la contrainte référentielle entre les bases de données à l'aide d'un déclencheur.


En gros, vous créez un déclencheur d'insertion et de mise à jour pour vérifier l'existence de la clé dans la table de clés primaires. Si la clé n'existe pas, annulez l'insertion ou la mise à jour, puis gérez l'exception.

Exemple:

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

Edited: Juste pour clarifier. Ce n'est pas la meilleure approche pour appliquer l'intégrité référentielle. Idéalement, vous voulez les deux tables dans la même base de données, mais si cela n’est pas possible. Ensuite, ce qui précède est un travail potentiel pour vous.

69
John Hartsock

Si vous avez besoin d'une intégrité irréprochable, disposez les deux tables dans une base de données et utilisez une contrainte FK. Si votre table parent se trouve dans une autre base de données, rien n'empêche quiconque de restaurer cette base de données parent à partir d'une ancienne sauvegarde. Vous avez ensuite des orphelins.

C'est pourquoi FK entre bases de données n'est pas pris en charge.

38
A-K

D'après mon expérience, le meilleur moyen de gérer cela lorsque la source principale d'informations faisant autorité pour deux tables liées doit se trouver dans deux bases de données distinctes consiste à synchroniser une copie de la table de l'emplacement principal à l'emplacement secondaire (à l'aide de SQL ou SSIS avec vérification d'erreur appropriée - vous ne pouvez pas tronquer et repeupler une table tant qu'elle contient une référence de clé étrangère, il existe donc plusieurs façons de paramétrer le chat sur la mise à jour de la table.

Ajoutez ensuite une relation FK traditionnelle au deuxième emplacement de la table, qui est en réalité une copie en lecture seule.

Vous pouvez utiliser un travail déclencheur ou planifié dans l'emplacement principal pour maintenir la copie à jour.

24
Cade Roux

Vous pouvez utiliser la contrainte de vérification avec une fonction définie par l'utilisateur pour effectuer la vérification. C'est plus fiable qu'un déclencheur. Il peut être désactivé et réactivé si nécessaire de la même manière que les clés étrangères et revérifié après une restauration de la base de données2.

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)
17
Camilo J

La réponse courte est que SQL Server (à partir de SQL 2008) ne prend pas en charge les clés étrangères de bases de données croisées, comme l'indique le message d'erreur.

Si vous ne pouvez pas avoir d'intégrité référentielle déclarative (le FK), vous pouvez atteindre le même objectif à l'aide de déclencheurs. C'est un peu moins fiable, car la logique que vous écrivez peut comporter des bugs, mais elle vous y conduira tout de même.

Voir la documentation SQL @ http://msdn.Microsoft.com/en-us/library/aa258254%28v=sql.80%29.aspx Quel état:

Les déclencheurs sont souvent utilisés pour appliquer les règles métier et l'intégrité des données. SQL Server fournit une intégrité référentielle déclarative (DRI) via les instructions de création de table (ALTER TABLE et CREATE TABLE); Cependant, DRI ne fournit pas d'intégrité référentielle entre bases de données. Pour appliquer l'intégrité référentielle (règles concernant les relations entre les clés primaire et étrangère des tables), utilisez les contraintes de clé primaire et étrangère (les mots clés PRIMARY KEY et FOREIGN KEY de ALTER TABLE et CREATE TABLE). Si des contraintes existent sur la table de déclencheur, elles sont vérifiées après l'exécution du déclencheur INSTEAD OF et avant l'exécution du déclencheur AFTER. Si les contraintes sont violées, les actions du déclencheur INSTEAD OF sont annulées et le déclencheur AFTER n'est pas exécuté (déclenché).

Il y a aussi une discussion OK sur SQLTeam - http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=31135

3
EBarr

Comme l'indique le message d'erreur, cela n'est pas pris en charge sur le serveur SQL. Le seul moyen de garantir l’intégrité référentielle consiste à utiliser des déclencheurs.

0
Jan