L'istruzione ALTER TABLE è in conflitto con il vincolo FOREIGN KEY


184

Ho un problema quando provo ad aggiungere una chiave esterna alla mia tblDomaretabella; cosa sto facendo di sbagliato qui?

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);

Messaggio di errore:

L'istruzione ALTER TABLE è in conflitto con il vincolo FOREIGN KEY "FK_ tblDomare _PersN__5F7E2DAC". Il conflitto si è verificato nel database "almu0004", tabella "dbo.tblBana", colonna "BanNR".

Risposte:


333

Si è verificato perché hai tentato di creare una chiave esterna da tblDomare.PersNRa tblBana.BanNRma / e i valori in tblDomare.PersNRnon corrispondevano a nessuno dei valori in tblBana.BanNR. Non è possibile creare una relazione che viola l'integrità referenziale.


87
Questa è stata la risposta per me, ma ho ancora difficoltà a capire dove fosse il problema, quindi darò l'esempio di un laico. Se hai una tabella denominata "Ordini" e una tabella denominata "Clienti" e hai eliminato alcuni vecchi clienti, ma non i loro ordini, riceverai questo errore se decidi di creare una chiave esterna dagli ordini. .ID. Alcuni ordini non hanno più un cliente corrispondente, quindi è impossibile aggiungere la chiave esterna.
Chad Hedgcock,

10
Ecco una query per verificare i valori errati: selezionare referrerTable.referenceColumn distinto da referrerTable sinistra join referableTable on referTable.referenceColumn = referrerTable.referenceColumn dove riferitoTable.referenceColumn è null;
jumxozizi,

6
In un pizzico, puoi anche usare l'opzione "ALTER TABLE tablename WITH NOCHECK ..." per aggiungere l'FK. Ciò consentirà di aggiungere la relazione, anche se i dati esistenti interrompono il vincolo. È ovviamente meglio ripulire prima i dati, ma questo ti dà almeno un'altra opzione.
DaveInMaine,

2
@DaveInMaine Se si disattivano i vincoli del database "quando lo si desidera", vorrei chiedere perché in primo luogo preoccuparsi di loro e non semplicemente saltarli se non si è interessati all'integrità del database.
Smutje,

1
che pessimo messaggio di errore. visto prima, ma mi ha colto completamente alla sprovvista proprio ora pensando che qualcosa fosse corrotto
Simon_Weaver,

43

Questa domanda mi è stata molto utile. Mostra tutti i valori che non hanno corrispondenze

select FK_column from FK_table
WHERE FK_column NOT IN
(SELECT PK_column from PK_table)

37

Prova questa soluzione:

Nella tabella è presente un elemento dati il ​​cui valore associato non esiste nella tabella che si desidera utilizzare come tabella chiave primaria. Rendi vuota la tua tabella o aggiungi il valore associato alla seconda tabella.


29

È possibile creare la chiave esterna utilizzando ALTER TABLE tablename WITH NOCHECK ..., che consentirà i dati che violano la chiave esterna.

"ALTER TABLE tablename WITH NOCHECK ..." opzione per aggiungere l'FK - Questa soluzione ha funzionato per me.


17
Tenere presente che consentire tali violazioni vanifica lo scopo del vincolo di chiave esterna.
riformato il

Pericoloso...!!! Dovrebbe essere usato solo se non vuoi perdere i dati attualmente nella tabella. Ma anche allora, perché non fare un backup e quindi rimuovere gli ID non validi.
Andrei Bazanov,

Ho bisogno di implementare tramite Java / Spring / Code per farlo, non direttamente tramite query SQL, qualsiasi ideia come fare questo con il seguente codice: @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.DETACH) @JoinTable(name = "tbUsuariosTipoOcorrencia", joinColumns = { @JoinColumn(name = "idUsuario") }, inverseJoinColumns = { @JoinColumn(name = "idTipoOcorrencia") }) e ho fatto questo risolvere tramite query del database:alter table tbUsuariosTipoOcorrencia WITH NOCHECK add constraint FKnbxg3ua7b8c5d53wps69q6jh foreign key (idUsuario) references tbUsuarios
Francisco Souza

11

Immagino, un valore di colonna in una tabella di chiavi esterne dovrebbe corrispondere al valore di colonna della tabella di chiavi primarie. Se stiamo cercando di creare un vincolo di chiave esterna tra due tabelle in cui il valore all'interno di una colonna (che diventerà la chiave esterna) è diverso dal valore di colonna della tabella della chiave primaria, verrà generato il messaggio.

Pertanto, si consiglia sempre di inserire solo i valori nella colonna Chiave esterna presenti nella colonna Tabella chiave primaria.

Per es. Se la colonna della tabella primaria ha i valori 1, 2, 3 e nella colonna Chiave esterna i valori inseriti sono diversi, la query non verrà eseguita poiché prevede che i valori siano compresi tra 1 e 3.


11

Prima di aggiungere la chiave esterna alla tabella, procedere come segue

  1. Assicurarsi che la tabella deve essere vuota o che i dati della colonna debbano corrispondere.
  2. Assicurarsi che non sia nullo.
  3. Se la tabella contiene non andare a progettare e modificare, fallo manualmente.

    modifica tabella Tabella 1 aggiungi riferimenti a chiave esterna (nome colonna) Tabella 2 (nome colonna)

    alter table Tabella 1 alter column Attributo Nome colonna non nullo


10

Pulisci i tuoi dati dalle tue tabelle e poi crea relazioni tra di loro.


Grazie, max. ha funzionato per me se hanno dati anche se le relazioni sono perfette il comando Aggiorna-Database non funzionerà.
robert jebakumar2

Non è necessario rimuovere alcun dato purché sia ​​valido in base alla chiave esterna che viene creata.
jumxozizi,

7

Prova DELETEi dati correnti da tblDomare.PersNR. Perché i valori in tblDomare.PersNRnon corrispondono a nessuno dei valori in tblBana.BanNR.


@agenc ho risposto alla tua domanda?
Pensatore Bell,

3

ho avuto questo errore anche quando si riferiva a Smutje assicurandomi di non avere un valore nella colonna chiave esterna della tabella di chiave esterna di base che non sia nella tabella di riferimento, cioè (ogni valore nella tabella chiave esterna di base (valore di una colonna che è chiave esterna) deve trovarsi anche nella colonna della tabella di riferimento) è consigliabile svuotare prima la tabella delle chiavi esterne di base, quindi impostare le chiavi esterne


2

i dati che hai inserito in una tabella (tbldomare) non corrispondono a quelli che hai assegnato alla tabella delle chiavi primarie. scrivi tra tbldomare e aggiungi questa parola (con nocheck) quindi esegui il tuo codice.

per esempio hai inserito una tabella per questi dati

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

e hai assegnato una foreign keytabella per accettare solo 1,2,3.

hai due soluzioni, una è cancellare i dati che hai inserito in una tabella, quindi eseguire il codice. un altro è scrivere questa parola (con nocheck) inserirla tra il nome della tabella e aggiungere in questo modo

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

2

Questo succede a me, dal momento che sto progettando il mio database, noto che cambio il mio seed sulla mia tabella principale, ora la tabella relazionale non ha chiave esterna sulla tabella principale.

Quindi ho bisogno di troncare entrambe le tabelle e ora funziona!


2

Dovresti vedere se le tue tabelle contengono dati nelle righe. Se "sì" allora si dovrebbe troncare la tabella (s), oppure si può fare loro di avere lo stesso numero di dati a tblDomare.PersNRda tblBana.BanNRe morsa-verse.


2

Smutje ha ragione e Chad HedgeCock ha offerto un ottimo esempio di profano. Mi piacerebbe basarmi sull'esempio di Chad offrendo un modo per trovare / eliminare quei record. Useremo il cliente come genitore e l'ordine come figlio. CustomerId è il campo comune.

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

se stai leggendo questa discussione ... otterrai risultati. Questi sono bambini orfani. seleziona * da Ordine figlio a sinistra Unisci cliente Genitore su Child.CustomerId = Parent.CustomerId dove Parent.CustomerId è null Nota il conteggio delle righe in basso a destra.

Vai a verificare con chiunque tu abbia bisogno di eliminare queste righe!

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

Esegui il primo bit. Controlla che il conteggio delle righe = quello che ti aspettavi

impegnare il tran

commit tran 

Stai attento. La programmazione sciatta di qualcuno ti ha messo in questo casino. Assicurati di capire il perché prima di eliminare gli orfani. Forse il genitore deve essere ripristinato.


Grazie per la risposta. Sto giocando con il database stackoverflow (in realtà gamedev) e ho trovato due NULL quando ho lasciato i badge JOIN con gli utenti. Nessuna meraviglia che i vincoli non funzionassero ...
Nicholas Humphrey,

1

Nel mio scenario, usando EF, dopo aver provato a creare questa nuova chiave esterna su dati esistenti, stavo tentando erroneamente di popolare i dati (creare i collegamenti) DOPO aver creato la chiave esterna.

La correzione consiste nel popolare i dati prima di creare la chiave esterna poiché li controlla tutti per vedere se i collegamenti sono effettivamente validi. Quindi non potrebbe funzionare se non lo hai ancora popolato.


1

Riscontro qualche problema nel mio progetto.

inserisci qui la descrizione dell'immagine

Nella tabella figlio, non esiste alcun ID record uguale a 1 e 11

mage

Ho inserito la tabella DEAL_ITEM_THIRD_PARTY_PO con ID uguale a 1 e 11, quindi posso creare FK


0

Elimina prima i dati da quella tabella e quindi esegui nuovamente la migrazione. Avrai successo


0

Quando si definisce una chiave esterna nella tabella B che fa riferimento alla chiave primaria della tabella A significa che quando un valore è in B, deve essere in A. Questo per evitare modifiche incoerenti alle tabelle.

Nel tuo esempio, le tue tabelle contengono:

tblDomare con PRIMARY KEY (PersNR):

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

tblBana:

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

Questa dichiarazione:

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

dice che ogni riga tblDomarecon chiave PersNRdeve avere una corrispondenza nella tabella tblBanasu chiave BanNR. Il tuo errore è perché hai inserito delle righe tblDomaresenza corrispondenza in tblBana.

2 soluzioni per risolvere il problema: - aggiungere linee tblBanacon BanNR in (6811034679, 7606091347, 8508284163) - or remove all lines intblDomare that have no correspondance intblBana` (ma la tabella sarebbe vuota)

Consiglio generale : è necessario disporre del vincolo di chiave esterna prima di popolare le tabelle. Le chiavi esterne sono qui per impedire all'utente della tabella di riempire le tabelle con incoerenze.


-3

e solo FYI, nel caso in cui si eseguano tutti i controlli di riferimento dei dati e non si rilevino dati errati ... a quanto pare non è possibile creare un vincolo di chiave esterna tra due tabelle e campi in cui tali campi sono la chiave primaria in entrambe le tabelle! Non chiedermi come lo so.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.