L'utilisation de plusieurs clés étrangères sur la même colonne dans SQL Server

10

SQL Server me permet de créer plusieurs clés étrangères sur une colonne, et chaque fois en utilisant un nom différent, je peux créer une autre clé faisant référence au même objet. Fondamentalement, toutes les clés définissent la même relation. Je veux savoir à quoi sert d'avoir plusieurs clés étrangères définies sur la même colonne et faisant référence à la même colonne dans une autre table. Quel est l'avantage de cela que SQL Server nous permet de faire une chose comme ça?

entrez la description de l'image ici

igelr
la source

Réponses:

12

Il n'y a aucun avantage à avoir des contraintes redondantes qui ne diffèrent que par leur nom. De même, il n'y a aucun avantage à avoir des index redondants qui ne diffèrent que par leur nom. Les deux ajoutent des frais généraux sans valeur.

Le moteur de base de données SQL Server ne vous en empêche pas. De bonnes conventions de dénomination des contraintes (par exemple FK_ReferencingTable_ReferencedTable) peuvent aider à protéger une personne contre de telles erreurs.

Dan Guzman
la source
17

SQL Server vous permet de faire beaucoup de choses stupides.

Vous pouvez même créer une clé étrangère sur une colonne se référençant elle - même - malgré le fait que cela ne peut jamais être violé car chaque ligne rencontrera la contrainte sur elle-même.

Un cas de bord où la possibilité de créer deux clés étrangères sur la même relation serait potentiellement utile est parce que l'index utilisé pour valider les clés étrangères est déterminé au moment de la création. Si un meilleur index (c'est-à-dire plus étroit) apparaît plus tard, cela permettrait de créer une nouvelle contrainte de clé étrangère liée au meilleur index, puis la contrainte d'origine supprimée sans aucun écart sans contrainte active.

(Comme dans l'exemple ci-dessous)

CREATE TABLE T1(
    T1_Id INT PRIMARY KEY CLUSTERED  NOT NULL,
    Filler CHAR(4000) NULL,
) 

INSERT INTO T1 VALUES (1, '');

CREATE TABLE T2(
    T2_Id INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
    T1_Id INT NOT NULL CONSTRAINT FK REFERENCES T1 (T1_Id), 
    Filler CHAR(4000) NULL,
)


ALTER TABLE T1 ADD CONSTRAINT
    UQ_T1 UNIQUE NONCLUSTERED(T1_Id) 


/*Execution Plan uses clustered index*/ 
INSERT INTO T2 VALUES (1,1) 

ALTER TABLE T2  WITH CHECK ADD  CONSTRAINT FK2 FOREIGN KEY(T1_Id)
REFERENCES T1 (T1_Id)    

ALTER TABLE T2 DROP CONSTRAINT FK

/*Now Execution Plan now uses non clustered index*/    
INSERT INTO T2 VALUES (1,1)    

DROP TABLE  T2, T1;

En aparté pour la période intérimaire alors que les deux contraintes existent, tous les inserts finissent par être validés par rapport aux deux indices.

Martin Smith
la source
Une transaction peut-elle être utilisée pour garantir la même mise à jour des contraintes sans espace? Cette méthode sans transaction est-elle meilleure en raison d'un verrouillage moindre, peut-être?
binki
13

Il est inutile d'avoir des contraintes de clé étrangère identiques., C'est-à-dire sur les mêmes colonnes et référençant les mêmes tables et colonnes.

C'est comme avoir le même chèque 2 fois ou plus.

ypercubeᵀᴹ
la source
-Pas d'accord. Il est possible que la table principale ait besoin de deux vérifications distinctes. Voir l'exemple ci-dessous, l'expéditeur et le récepteur sont totalement différents - stackoverflow.com/questions/40400483/…
trex
@trex dont vous parlez quelque chose de différent. La question ici indique: "Je veux savoir à quoi sert d'avoir plusieurs clés étrangères qui sont définies sur la même colonne et référence à la même colonne dans une autre table ."
ypercubeᵀᴹ
@ ypercubeᵀᴹ - J'ai compris. Merci d'avoir précisé
trex
6

Même raison pour laquelle vous pouvez créer 50 index sur la même colonne, ajouter un deuxième fichier journal, définir la mémoire maximale du serveur à 20 Mo ... la plupart des gens ne feront pas ces choses, mais il peut y avoir des raisons légitimes de les faire occasionnellement, donc il n'y a pas avantage à créer des frais généraux dans le moteur pour ajouter des contrôles par rapport à des choses qui sont simplement mal avisées.

Aaron Bertrand
la source
2

Cela ressemble à une chose bleu-vert.

Lorsque vous commencez à passer du bleu au vert, vous devez créer temporairement des copies supplémentaires de choses.

Ce que nous voulons faire, c'est créer temporairement une clé étrangère supplémentaire CHECK WITH NOCHECKet ON UPDATE CASCADE ON DELETE SET NULL; cela signifie que c'est une clé étrangère qui fonctionne, mais les lignes existantes ne sont pas vérifiées lors de la création de la clé.

Plus tard, après avoir nettoyé toutes les lignes qui devraient correspondre, nous créerions la nouvelle clé étrangère sans aucune option de commande (la valeur par défaut est CHECK WITH CHECKcelle que vous souhaitez généralement) et supprimez la clé étrangère temporaire.

Notez que si vous venez de supprimer et de recréer la clé étrangère, certaines lignes de mémoire peuvent glisser par vous.

Joshua
la source