L'instruction ALTER TABLE était en conflit avec la contrainte FOREIGN KEY

201

J'ai un problème en essayant d'ajouter une clé étrangère à ma tblDomaretable; qu'est-ce que je fais de mal ici?

CREATE TABLE tblDomare
(PersNR VARCHAR (15) NOT NULL,
fNamn VARCHAR (15) NOT NULL,
eNamn VARCHAR (20) NOT NULL,
Erfarenhet VARCHAR (5),
PRIMARY KEY (PersNR));

INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (6811034679,'Bengt','Carlberg',10);

INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (7606091347,'Josefin','Backman',4);

INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (8508284163,'Johanna','Backman',1);

CREATE TABLE tblBana
(BanNR VARCHAR (15) NOT NULL,
PRIMARY KEY (BanNR));

INSERT INTO tblBana (BanNR)
Values (1);

INSERT INTO tblBana (BanNR)
Values (2);

INSERT INTO tblBana (BanNR)
Values (3);

ALTER TABLE tblDomare
ADD FOREIGN KEY (PersNR)
REFERENCES tblBana(BanNR);

Message d'erreur:

L'instruction ALTER TABLE était en conflit avec la contrainte FOREIGN KEY "FK_ tblDomare _PersN__5F7E2DAC". Le conflit s'est produit dans la base de données "almu0004", table "dbo.tblBana", colonne "BanNR".

user3162932
la source

Réponses:

352

Cela s'est produit parce que vous avez essayé de créer une clé étrangère de tblDomare.PersNRà tblBana.BanNRmais / et que les valeurs de tblDomare.PersNRne correspondent à aucune des valeurs de tblBana.BanNR. Vous ne pouvez pas créer une relation qui viole l'intégrité référentielle.

Smutje
la source
91
C'était la réponse pour moi, mais j'ai toujours eu du mal à comprendre où était le problème, alors je vais donner l'exemple d'un profane. Si vous avez une table nommée `` Commandes '' et une table nommée `` Clients '' et que vous avez supprimé certains anciens clients, mais pas leurs commandes, vous obtiendrez cette erreur si vous décidez de créer une clé étrangère à partir des commandes. .Id. Certaines commandes n'ont plus de client correspondant, il est donc impossible d'ajouter la clé étrangère.
Chad Hedgcock
10
Voici une requête pour vérifier les valeurs incorrectes: sélectionnez referrerTable.referenceColumn distinct de referrerTable jointure gauche référencéTable sur référencéTable.referenceColumn = referrerTable.referenceColumn où refererTable.referenceColumn est nul;
jumxozizi
6
À la rigueur, vous pouvez également utiliser l'option "ALTER TABLE tablename WITH NOCHECK ..." pour ajouter le FK. Cela vous permettra d'ajouter la relation, même si les données existantes cassent la contrainte. Il est évidemment préférable de nettoyer d'abord vos données, mais cela vous donne au moins une autre option.
DaveInMaine
2
@DaveInMaine Si l'on désactive les contraintes de base de données "quand on le souhaite", je me demanderais pourquoi s'embêter avec elles en premier lieu et ne pas simplement les sauter si l'on n'est pas intéressé par l'intégrité de la base de données.
Smutje
1
quel mauvais message d'erreur. vu avant mais m'a pris complètement au dépourvu en pensant que quelque chose était corrompu
Simon_Weaver
47

Cette requête m'a été très utile. Il montre toutes les valeurs qui n'ont aucune correspondance

select FK_column from FK_table
WHERE FK_column NOT IN
(SELECT PK_column from PK_table)
dantey89
la source
Très simple et extrêmement utile lorsque vous essayez de trouver les entrées défectueuses. Merci beaucoup!
TheMSG
merci des tas! belle réponse, belle addition
Egli Becerra
41

Essayez cette solution:

Il existe un élément de données dans votre table dont la valeur associée n'existe pas dans la table que vous souhaitez utiliser comme table de clé primaire. Rendez votre table vide ou ajoutez la valeur associée à la deuxième table.

PatsonLeaner
la source
1
Cela fonctionne pour moi .... merci
user3623037
29

Il est possible de créer la clé étrangère en utilisant ALTER TABLE tablename WITH NOCHECK ..., ce qui autorisera les données qui violent la clé étrangère.

Option "ALTER TABLE tablename WITH NOCHECK ..." pour ajouter le FK - Cette solution a fonctionné pour moi.

Ankita Biswas
la source
18
N'oubliez pas que permettre de telles violations va à l'encontre de l'objectif de la contrainte de clé étrangère.
réformé
Dangereux...!!! Ne doit être utilisé que si vous ne souhaitez pas perdre les données actuellement dans le tableau. Mais même dans ce cas, pourquoi ne pas faire une sauvegarde, puis supprimer les identifiants invalides.
Andrei Bazanov
Je dois implémenter via java / spring / code pour le faire, pas directement via une requête SQL, toute idée comment faire cela avec le code suivant: @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.DETACH) @JoinTable(name = "tbUsuariosTipoOcorrencia", joinColumns = { @JoinColumn(name = "idUsuario") }, inverseJoinColumns = { @JoinColumn(name = "idTipoOcorrencia") }) et je l'ai fait résoudre via une requête de base de données:alter table tbUsuariosTipoOcorrencia WITH NOCHECK add constraint FKnbxg3ua7b8c5d53wps69q6jh foreign key (idUsuario) references tbUsuarios
Francisco Souza
12

Je suppose qu'une valeur de colonne dans une table de clé étrangère doit correspondre à la valeur de colonne de la table de clé primaire. Si nous essayons de créer une contrainte de clé étrangère entre deux tables où la valeur à l'intérieur d'une colonne (qui va être la clé étrangère) est différente de la valeur de colonne de la table de clé primaire, alors il lancera le message.

Il est donc toujours recommandé de n'insérer que les valeurs dans la colonne Clé étrangère qui sont présentes dans la colonne Table de clé primaire.

Par ex. Si la colonne de la table principale a les valeurs 1, 2, 3 et que dans la colonne de clé étrangère les valeurs insérées sont différentes, la requête ne sera pas exécutée car elle s'attend à ce que les valeurs soient comprises entre 1 et 3.

sam05
la source
12

Avant d'ajouter une clé étrangère à la table, procédez comme suit

  1. Assurez-vous que la table doit être vide ou que les données de la colonne doivent correspondre.
  2. Assurez-vous qu'il n'est pas nul.
  3. Si le tableau contient n'allez pas à la conception et à la modification, faites-le manuellement.

    alter table Table 1 ajouter des références de clé étrangère (nom de colonne) Table 2 (nom de colonne)

    alter table Table 1 alter column Attribut de nom de colonne non nul

GirishBabuC
la source
11

Nettoyez vos données de vos tables et établissez une relation entre elles.

max
la source
Merci, max. cela a fonctionné pour moi s'ils ont des données même si les relations sont parfaites, la commande Update-Database ne fonctionnera pas.
robert jebakumar2
Il n'est pas nécessaire de supprimer des données tant qu'elles sont valides selon la clé étrangère en cours de création.
jumxozizi
8

Essayez DELETEles données actuelles de tblDomare.PersNR. Parce que les valeurs de tblDomare.PersNRne correspondent à aucune des valeurs de tblBana.BanNR.

Penseur Bell
la source
@agenc ai-je répondu à votre question?
Thinker Bell
3

J'ai eu cette erreur aussi comme Smutje a référé assurez-vous que vous n'avez pas une valeur dans la colonne de clé étrangère de votre table de clé étrangère de base qui n'est pas dans votre table de référence, c'est-à-dire (chaque valeur de votre table de clé étrangère de base (valeur d'une colonne qui est clé étrangère) doit également être dans la colonne de votre table de référence) il est bon de vider d'abord votre table de clé étrangère de base, puis de définir des clés étrangères

ako
la source
2

les données que vous avez entrées dans une table (tbldomare) ne correspondent pas aux données que vous avez attribuées à une table de clé primaire. écrivez entre tbldomare et ajoutez ce mot (sans vérification) puis exécutez votre code.

par exemple vous avez entré une table tbldomar ces données

INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (6811034679,'Bengt','Carlberg',10);

et vous avez attribué une foreign keytable pour accepter uniquement1,2,3 .

vous avez deux solutions l'une est de supprimer les données que vous avez entrées dans une table puis d'exécuter le code. une autre est d'écrire ce mot (sans vérification), placez-le entre le nom de votre table et ajoutez comme ceci

ALTER TABLE  tblDomare with nocheck
ADD FOREIGN KEY (PersNR)
REFERENCES tblBana(BanNR);
khadar
la source
2

Cela m'arrive, puisque je conçois ma base de données, je remarque que je change ma graine sur ma table principale, maintenant la table relationnelle n'a pas de clé étrangère sur la table principale.

J'ai donc besoin de tronquer les deux tables, et cela fonctionne maintenant!

Willy David Jr
la source
2

Vous devriez voir si vos tables contiennent des données sur les lignes. Si « oui » , alors vous devez tronquer la table (s) ou bien vous pouvez les faire pour avoir le même nombre de données à tblDomare.PersNRla tblBana.BanNRet vice-verse.

adrianex03
la source
2

Smutje a raison et Chad HedgeCock a donné l'exemple d'un grand profane. J'aimerais tirer parti de l'exemple de Chad en offrant un moyen de trouver / supprimer ces enregistrements. Nous utiliserons le Client comme parent et l'Ordre comme enfant. CustomerId est le champ commun.

select * from Order Child 
left join Customer Parent on Child.CustomerId = Parent.CustomerId
where Parent.CustomerId is null 

si vous lisez ce fil ... vous obtiendrez des résultats. Ce sont des enfants orphelins. select * from Order Child left join Customer Parent on Child.CustomerId = Parent.CustomerId où Parent.CustomerId est null Notez le nombre de lignes en bas à droite.

Vérifiez avec qui vous en avez besoin que vous allez supprimer ces lignes!

begin tran 
delete Order
from Order Child 
left join Customer Parent on Child.CustomerId = Parent.CustomerId
where Parent.CustomerId is null 

Exécutez le premier bit. Vérifiez que le nombre de lignes = ce que vous attendiez

commettre le tran

commit tran 

Faites attention. La programmation bâclée de quelqu'un vous a mis dans ce pétrin. Assurez-vous de comprendre pourquoi avant de supprimer les orphelins. Peut-être que le parent doit être rétabli.

Greg
la source
Merci pour la réponse. Je joue avec la base de données stackoverflow (gamedev en fait) et j'ai trouvé deux NULL lorsque JE LEFT JOIN Badges with Users. Pas étonnant que les contraintes n'aient pas fonctionné ...
Nicholas Humphrey
2

Dans mon scénario, en utilisant EF, en essayant de créer cette nouvelle clé étrangère sur des données existantes, j'essayais à tort de remplir les données (créer les liens) APRÈS la création de la clé étrangère.

Le correctif consiste à remplir vos données avant de créer la clé étrangère car il les vérifie toutes pour voir si les liens sont effectivement valides. Cela ne pourrait donc pas fonctionner si vous ne l'avez pas encore rempli.

Jeromej
la source
2

Veuillez d'abord supprimer les données de cette table, puis réexécuter la migration. Vous obtiendrez du succès

M Arslan Riaz
la source
2

Lorsque vous définissez une clé étrangère dans la table B faisant référence à la clé primaire de la table A, cela signifie que lorsqu'une valeur est dans B, elle doit être dans A. Ceci afin d'éviter des modifications incohérentes des tables.

Dans votre exemple, vos tableaux contiennent:

tblDomare avec PRIMARY KEY (PersNR):

PersNR     |fNamn     |eNamn      |Erfarenhet
-----------|----------|-----------|----------
6811034679 |'Bengt'   |'Carlberg' |10
7606091347 |'Josefin' |'Backman'  |4
8508284163 |'Johanna' |'Backman'  |1
---------------------------------------------

tblBana:

BanNR
-----
1
2
3
-----

Cette déclaration:

ALTER TABLE tblDomare
ADD FOREIGN KEY (PersNR)
REFERENCES tblBana(BanNR);

dit que toute ligne tblDomareavec clé PersNRdoit avoir une correspondance dans la table tblBanasur la clé BanNR. Votre erreur est due au fait que vous avez inséré des lignes tblDomaresans correspondance tblBana.

2 solutions pour résoudre votre problème: - soit ajouter des lignes tblBanaavec BanNR in (6811034679, 7606091347, 8508284163) - or remove all lines intblDomarethat have no correspondance in tblBana` (mais votre table serait vide)

Conseil général : vous devez avoir la contrainte de clé étrangère avant de remplir les tables. Les clés étrangères sont là pour empêcher l'utilisateur de la table de remplir les tables avec des incohérences.

Belka
la source
1
"Votre erreur est que vous avez des lignes insérées dans tblDomare sans correspondance dans tblBana." C'était ça!
mrkarp le
1

Je rencontre un problème dans mon projet.

entrez la description de l'image ici

Dans la table enfant, aucun ID d'enregistrement n'est égal à 1 et 11

mage

J'ai inséré la table DEAL_ITEM_THIRD_PARTY_PO dont l'ID est égal à 1 et 11, puis je peux créer FK

Metin Atalay
la source
-3

et juste pour info, au cas où vous feriez toutes vos vérifications de référence de données et ne trouveriez aucune mauvaise donnée ... apparemment, il n'est pas possible de créer une contrainte de clé étrangère entre deux tables et champs où ces champs sont la clé primaire dans les deux tables! Ne me demandez pas comment je sais cela.

Doug Boude
la source