Impossibile aggiungere o aggiornare una riga figlio: un vincolo di chiave esterna non riesce


174

Tabella 1

+----------+-------------+------+-----+---------+----------------+
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| UserID   | int(11)     | NO   | PRI | NULL    | auto_increment |
| Password | varchar(20) | NO   |     |         |                |
| Username | varchar(25) | NO   |     |         |                |
| Email    | varchar(60) | NO   |     |         |                |
+----------+-------------+------+-----+---------+----------------+

Tavolo 2

+------------------+--------------+------+-----+---------+----------------+
| Field            | Type         | Null | Key | Default | Extra          |
+------------------+--------------+------+-----+---------+----------------+
| UserID           | int(11)      | NO   | MUL |         |                |
| PostID           | int(11)      | NO   | PRI | NULL    | auto_increment |
| Title            | varchar(50)  | NO   |     |         |                |
| Summary          | varchar(500) | NO   |     |         |                |
+------------------+--------------+------+-----+---------+----------------+

Errore:

com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: 
Cannot add or update a child row: a foreign key constraint fails 
(`myapp/table2`, CONSTRAINT `table2_ibfk_1` FOREIGN KEY (`UserID`) 
REFERENCES `table1` (`UserID`)) 

Cosa ho fatto di sbagliato? Ho letto http://www.w3schools.com/Sql/sql_foreignkey.asp e non vedo cosa non va.


4
Puoi pubblicare la query che attiva l'errore?
Umido,

38
In breve, stai cercando di inserire / aggiornare un valore in table2.UserIDcui non esiste table1.UserID.
Joe Stefanelli,

Non so perché, ma dopo aver spostato il mio database da un ambiente Windows a Linux, ho dovuto eliminare e ricreare una relazione (è stato allora che ho notato il problema). Il valore esisteva, ma rimuovendo e aggiungendo nuovamente la relazione è stato risolto. Potrebbe essere necessario stare molto attenti a farlo ovviamente.
johnsnails,

Risposte:


235

Questo errore viene visualizzato perché stai tentando di aggiungere / aggiornare una riga in table2cui non esiste un valore valido per il UserIDcampo in base ai valori attualmente memorizzati table1. Se pubblichi altro codice, posso aiutarti a diagnosticare la causa specifica.


PreparedStatement st = connection.prepareStatement ("Inserisci in table2 (UserID, PostID, Title, Summary)" + "valori (UserID,?,?,?)");
Tom,

15
non so a cosa serva il downvote; la mia risposta è perfettamente valida e corretta.
Brian Driscoll,

Hmm ... non è sicuramente una buona idea mescolare parametri nominati con parametri senza nome nell'istruzione preparata. dovrebbe essere "valori (?,?,?,?)" con il valore appropriato per UserID specificato nell'istruzione execute.
Brian Driscoll,

Quindi devo fare un'altra istruzione SQL per ottenere userid da table1?
Tom,

5
Molto probabilmente uno 0, sostituiscilo con Null se è il caso
Jeffrey Nicholson Carré

123

Significa che stai cercando di inserire in table2un UserIDvalore in cui non esiste table1.


104

Un semplice trucco può essere quello di disabilitare i controlli delle chiavi esterne prima di eseguire qualsiasi operazione sul tavolo. Basta interrogare

SET FOREIGN_KEY_CHECKS=0

Ciò disabiliterà la corrispondenza della chiave esterna rispetto a qualsiasi altra tabella. Dopo aver finito con la tabella, abilitala di nuovo

SET FOREIGN_KEY_CHECKS=1

Questo funziona per me molte volte.


Come lo uso ??
Sachin di Pune il

2
@SachinfromPune basta aggiungere SET FOREIGN_KEY_CHECKS = 0; all'inizio del file mysql e SET FOREIGN_KEY_CHECKS = 1; alla fine del file mysql, reimportare i dati
inrsaurabh,

1
Non è problematico? Perdi integrità referenziale, giusto?
roadrunner66,

L'integrità referenziale è supportata dalla presenza delle voci di indice corrette. Finché hai le chiavi e gli indici corretti, dovresti essere in grado di disabilitare il controllo delle chiavi durante un input in blocco.
Vernon Keenan,

46

Ho scoperto un altro caso strano: se si crea accidentalmente una chiave esterna da una tabella InnoDB a una tabella MyISAM, MySQL genera questo errore al momento dell'inserimento anche se i dati sono altrimenti validi.

Vedi http://nick.zoic.org/art/mysql-foreign-key-error/


1
Sì, ho lo stesso problema. Due tabelle dovrebbero essere InnoDB!
emeraldhieu,

2
Ho avuto lo stesso problema, grazie per il suggerimento. Ecco un link alla documentazione di MySQL su come convertire le tabelle da MyISAM a InnoDB dev.mysql.com/doc/refman/5.7/it/… TLDR: ALTER TABLE table_name ENGINE = InnoDB;
Guilherme Vaz,

In effetti, questo è stato il caso nel mio database. Ho deciso di cambiare il motore MyISAM in InnoDB. Finalmente, posso lavorare con il database come volevo.
Mike,

17

Stai ricevendo questo errore perché ci sono alcuni valori int table2.UserIDinesistenti table1.UserID(suppongo che tu abbia impostato il table2.UserIDvalore manualmente prima di creare questa chiave esterna).
Un esempio per questa scena: table1.UserIDottenere valori 1,2,3 e table2.UserIDottenere valori 4 (aggiungi per manuale). Quindi, quando si crea una chiave esterna, non possono trovare UserID = 4da table1e l'errore si verificherà.
Per correggere questo errore, basta rimuovere UserID = 4da table2o si può svuotare ciascuno di essi e quindi creare la chiave esterna e.
In bocca al lupo!


11

Mi ci è voluto un po 'di tempo per capire. In poche parole, la tabella che fa riferimento all'altra tabella contiene già dei dati e uno o più dei suoi valori non esistono nella tabella padre.

es. Table2 contiene i seguenti dati:

UserID    PostID    Title    Summary
5         1         Lorem    Ipsum dolor sit

Tabella 1

UserID    Password    Username    Email
9         ********    JohnDoe     john@example.com

Se si tenta di ALTER table2 e si aggiunge una chiave esterna, la query avrà esito negativo poiché UserID = 5 non esiste in Table1.


10

Se hai inserito una riga nella tabella 1 prima di creare la chiave esterna nella tabella 2, otterrai un errore di vincolo della chiave esterna, poiché il valore di incremento automatico è 2 nella tabella 1 e 1 nella tabella 2. Per risolvere questo problema, devi tronca la tabella 1 e riporta il valore di incremento automatico su 1. Quindi puoi aggiungere la tabella 2.


10

Assicurarsi di aver impostato il motore di database su InnoDB perché in MyISAM la chiave esterna e la transazione non sono supportate


2
ALTER TABLE my_table ENGINE = InnoDB;
Bishwas Mishra

7

Solo una piccola correzione: Rendi JoinColumn 'nullable = true' nella tabella 1 e 'UserID' campo 'insertable = false' e 'nullable = true' nella tabella2.

Nell'entità Table1:

@OneToMany(targetEntity=Table2.class, cascade = CascadeType.ALL)
@JoinColumn(name = "UserID", referencedColumnName = "UserID", nullable = true)
private List<Table2> table2List;

Nell'entità Table2:

@Column(insertable = false, nullable = true)
private int UserID;

Questa risposta ha risolto totalmente il mio problema, grazie mille per averlo condiviso. La chiave per me è stata l'aggiunta di @Column (insertable = false, nullable = true) sul file che sto usando come chiave di esclusione nell'oggetto / tabella figlio.
Israelm,

6

Ho appena avuto lo stesso problema, la soluzione è semplice.

Stai tentando di aggiungere un ID nella tabella figlio che non esiste nella tabella padre.

controlla bene, perché InnoDB ha il bug che a volte aumenta la colonna auto_increment senza aggiungere valori, ad esempio, INSERT ... ON DUPLICATE KEY


sul serio? non inserire un riferimento ID che non esiste ... basta controllare
Blaztix,

5

Ho avuto un problema simile. Stai tentando di applicare una chiave esterna su una tabella con contenuto e la colonna non è nulla. Hai due opzioni.

  1. Rendi nullable la colonna su cui desideri applicare i vincoli di chiave esterna. In questo modo si applicherà la chiave esterna sapendo che alcuni campi possono essere nulli. ( Questo è quello che ho fatto. )
  2. Creare la colonna su cui si desidera applicare il vincolo di chiave esterna, scrivere una query per inserire la chiave esterna nella colonna e quindi applicare i vincoli di chiave esterna. ( Non ho provato questo, ma dovrebbe funzionare )

4

Assicurarsi che il valore che si sta inserendo nella chiave esterna esista nella tabella padre. Questo mi ha aiutato. Ad esempio, se si inserisce user_id = 2in table.2, ma table.1non ha un user_id = 2, il vincolo genererà un errore. Il mio era il codice di errore n. 1452 per l'esattezza. Spero che questo aiuti chiunque altro con lo stesso problema!


3

Ho avuto lo stesso problema e la ragione era che avevo una riga nella prima tabella prima di aggiungere la chiave esterna.


1

Ho anche riscontrato lo stesso problema e il problema era che il valore delle voci della tabella padre non corrispondeva al valore della tabella chiave esterna. Quindi, per favore prova dopo cancella tutte le righe ..


Il vincolo richiede che gli utenti indicati nella Tabella2 siano già definiti nella Tabella1.
sorak,

1

Nel caso in cui le soluzioni fornite da altri non funzionassero. Quindi dovresti provare a controllare i motori di database delle tabelle padre e figlio. Nel mio caso, il motore delle tabelle padre era impostato su "MyISAM", modificandolo in InnoDB è stato risolto.

Spero che questo aiuti gli altri che sono bloccati come me.


1

Non si deve mettere un campo ondelete contro una cascata nel database.

Quindi imposta il campo onDelete su RESTRICT

Buona fortuna ♥


0

Ancora un altro strano caso che mi ha dato questo errore. Avevo erroneamente fatto riferimento alle mie chiavi esterne alla chiave primaria id. Ciò è stato causato da comandi errati di alter table. L'ho scoperto interrogando la tabella INFORMATION_SCHEMA (Vedi questa risposta dello stackoverflow)

La tabella era così confusa che non poteva essere riparata da nessun comando ALTER TABLE . Alla fine ho lasciato cadere il tavolo e l'ho ricostruito. Questo si è sbarazzato dell'integrità Errore.


0

Forse mentre hai aggiunto la userIDcolonna, ci sono dati per quella determinata tabella che è stata stabilita in modo che abbia un valore predefinito di 0, prova ad aggiungere la colonna senza ilNOT NULL


0

Ho anche ricevuto questo errore: "Impossibile aggiungere o aggiornare una riga figlio: un vincolo di chiave esterna non riesce". Ho riscontrato l'errore durante l'aggiunta di una nuova riga alla tabella padre

Il problema era che il vincolo di chiave esterna era stato definito nella tabella padre anziché nella tabella figlio.


0

Se si utilizza l'indice mysql o la relazione tra le tabelle, innanzitutto si eliminano le colonne (ad esempio: city_id) e si creano nuove colonne con lo stesso nome (ad esempio: city_id). Quindi riprovare ...


0

Esistono dati esistenti che la tabella contiene? In tal caso, prova a cancellare tutti i dati nella tabella in cui desideri aggiungere una chiave esterna. Quindi eseguire nuovamente il codice (aggiungere una chiave esterna).

Ho riscontrato questo problema così tante volte. Questa cancellazione di tutti i dati nella tabella funziona quando si desidera aggiungere una chiave esterna su una tabella esistente.

Spero che funzioni :)


0

Elimina gli indici del campo UserID della tabella2. È adatto a me


0

Tale errore si verifica quando si desidera aggiungere una chiave esterna con valori che non esistono nella chiave primaria della tabella padre. È necessario essere sicuri che la nuova chiave esterna UserID nella tabella2 abbia valori esistenti nella chiave primaria della tabella1, a volte per impostazione predefinita è nulla o uguale a 0.

È possibile innanzitutto aggiornare tutti i campi della chiave esterna nella tabella2 con un valore esistente nella chiave primaria della tabella1.

update table2 set UserID = 1 where UserID is null

Se si desidera aggiungere diversi UserID, è necessario modificare ogni riga con i valori desiderati.


-1

vincolo chiave esterna tabella figlio non riesce

Questo problema può sorgere a causa del seguente motivo:

Se lo stai facendo in Spring mvc, devi descrivere esplicitamente il tipo di id, perché a volte mysql non riesce a riconoscere il tipo di id. quindi imposti esplicitamente come in entrambe le tabelle nella tua classe di entità@GeneratedValue (strategy = GenerationType.IDENTITY)

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.