J'essaie d'ajouter une nouvelle clé étrangère à une table existante où il y a des données dans la colonne à laquelle je veux apporter une modification.
En développement, j'ai essayé cela là où les données existent et n'existent pas. En l'absence de données, cela fonctionne bien.
ALTER TABLE [rpt].ReportLessonCompetency WITH CHECK
ADD CONSTRAINT [FK_Grade_TraineeGrade_Id]
FOREIGN KEY (Grade) REFERENCES [rpt].TraineeGrade(Id)
Là où il y a des données, j'obtiens l'erreur suivante
L'instruction ALTER TABLE était en conflit avec la contrainte FOREIGN KEY "FK_Grade_TraineeGrade_Id". Le conflit s'est produit dans la base de données "T_test", table "Core.Report.TraineeGrade", colonne 'Id'.
Je serais reconnaissant si quelqu'un pouvait me faire savoir ce que je dois faire afin de garantir que cela fonctionne là où les données existent et n'existent pas car je ne peux pas contrôler si la base de données en direct aura ou n'aura pas de données existantes.
Merci
Simon
Vous recevez probablement l'erreur car vous avez des enregistrements orphelins dans la table [rpt]. [ReportLessonCompetency]. Un enregistrement orphelin est un enregistrement dans une table enfant sans enregistrement parent correspondant dans la table parent. Dans votre cas, la [rpt]. [ReportLessonCompetency] contiendra des valeurs pour [Grade] qui n'existent pas dans la table [rpt] .TraineeGrade (Id).
Il existe 2 options pour créer la clé étrangère (bien qu'il n'y ait qu'une seule option valide imo).
Nettoyez vos données
Vous pouvez d'abord rechercher les enregistrements de la table enfant qui n'ont pas d'enregistrement parent correspondant. Ensuite, vous devez soit supprimer/mettre à jour ces enregistrements dans la table enfant, soit ajouter les enregistrements parents manquants à votre table parent. Ensuite, vous pourrez créer la contrainte de clé étrangère. C'est de loin la meilleure option car votre intégrité référentielle est garantie et votre clé étrangère sera fiable.
Vous pouvez rechercher des enregistrements orphelins en exécutant la requête suivante:
SELECT *
FROM [rpt].ReportLessonCompetency rlc
WHERE NOT EXISTS
(
SELECT 1
FROM [rpt].TraineeGrade tg
WHERE tg.Id = rlc.Grade
)
AVEC NOCHECK
L'autre option serait de créer la clé étrangère avec WITH NOCKECK
. SQL Server créera la clé étrangère sans vérifier les données existantes dans la table. Lorsque vous mettez à jour/insérez des données dans la table enfant, ces enregistrements seront toujours vérifiés. Par conséquent, votre clé étrangère sera marquée comme non fiable et l'optimiseur de requête ne tiendra pas compte de votre contrainte pour générer un plan d'exécution.
ici vous pouvez trouver un exemple de la façon dont les performances peuvent être affectées.
Vous pouvez éviter de vérifier les contraintes FOREIGN KEY par rapport aux données existantes en utilisant WITH NOCHECK.
ALTER TABLE [rpt].ReportLessonCompetency WITH NOCHECK
ADD CONSTRAINT [FK_Grade_TraineeGrade_Id]
FOREIGN KEY (Grade) REFERENCES [rpt].TraineeGrade(Id)
Je ne recommanderais pas de le faire car les violations de contraintes ignorées peuvent entraîner l'échec d'une mise à jour à un stade ultérieur. Vous devez plutôt nettoyer vos données.