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?
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.
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)
CREATETABLE T1(
T1_Id INT PRIMARYKEYCLUSTEREDNOTNULL,
Filler CHAR(4000)NULL,)INSERTINTO T1 VALUES(1,'');CREATETABLE T2(
T2_Id INT IDENTITY(1,1)PRIMARYKEYNOTNULL,
T1_Id INT NOTNULLCONSTRAINT FK REFERENCES T1 (T1_Id),
Filler CHAR(4000)NULL,)ALTERTABLE T1 ADDCONSTRAINT
UQ_T1 UNIQUENONCLUSTERED(T1_Id)/*Execution Plan uses clustered index*/INSERTINTO T2 VALUES(1,1)ALTERTABLE T2 WITHCHECKADDCONSTRAINT FK2 FOREIGNKEY(T1_Id)REFERENCES T1 (T1_Id)ALTERTABLE T2 DROPCONSTRAINT FK/*Now Execution Plan now uses non clustered index*/INSERTINTO T2 VALUES(1,1)DROPTABLE 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.
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.
-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 ."
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.
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.
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.
la source
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.
la source
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 NOCHECK
etON 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 CHECK
celle 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.
la source