Nie można dodać ani zaktualizować wiersza podrzędnego: ograniczenie klucza obcego kończy się niepowodzeniem

174

Tabela 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   |     |         |                |
+----------+-------------+------+-----+---------+----------------+

Tabela 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   |     |         |                |
+------------------+--------------+------+-----+---------+----------------+

Błąd:

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

Co zrobiłem źle? Czytam http://www.w3schools.com/Sql/sql_foreignkey.asp i nie widzę, co jest nie tak.

Tomek
źródło
4
Czy możesz opublikować zapytanie, które spowodowało błąd?
Wilgotny
38
Krótko mówiąc, próbujesz wstawić / zaktualizować wartość table2.UserID, która nie istnieje w table1.UserID.
Joe Stefanelli
Nie wiem dlaczego, ale po przeniesieniu mojej bazy danych ze środowiska Windows do Linuksa musiałem usunąć i odtworzyć relację (wtedy zauważyłem problem). Wartość istniała, ale usunięcie i ponowne dodanie relacji naprawiło ją. Oczywiście możesz być bardzo ostrożny.
johnsnails

Odpowiedzi:

235

Otrzymujesz ten błąd, ponieważ próbujesz dodać / zaktualizować wiersz table2, który nie ma prawidłowej wartości dla UserIDpola na podstawie wartości aktualnie przechowywanych w table1. Jeśli prześlesz więcej kodu, pomogę Ci zdiagnozować konkretną przyczynę.

Brian Driscoll
źródło
PreparedStatement st = connection.prepareStatement ("Wstaw do tabeli2 (identyfikator użytkownika, identyfikator postu, tytuł, podsumowanie)" + "wartości (identyfikator użytkownika,?,?,?)");
Tom
15
nie jestem pewien, za co jest skierowana przeciw; moja odpowiedź jest całkowicie uzasadniona i poprawna.
Brian Driscoll
Hmm ... zdecydowanie nie jest dobrym pomysłem mieszanie parametrów nazwanych z nienazwanymi w przygotowanej instrukcji. powinno to być „wartości (?,?,?,?)” z odpowiednią wartością ID użytkownika określoną w instrukcji wykonania.
Brian Driscoll
Więc muszę zrobić do innej instrukcji SQL, aby uzyskać identyfikator użytkownika z tabeli 1?
Tom
5
Najprawdopodobniej 0, zamień je na Null, jeśli tak jest
Jeffrey Nicholson Carré
123

Oznacza to, że próbujesz wstawić table2do UserIDwartości, która nie istnieje w table1.

Rami C
źródło
104

Prostym hackem może być wyłączenie sprawdzania klucza obcego przed wykonaniem jakiejkolwiek operacji na tabeli. Wystarczy zapytać

SET FOREIGN_KEY_CHECKS=0

Spowoduje to wyłączenie dopasowywania kluczy obcych do innych tabel. Po zakończeniu pracy ze stołem włącz ją ponownie

SET FOREIGN_KEY_CHECKS=1

To działa dla mnie wiele razy.

Sandeep Giri
źródło
Jak tego używam?
Sachin z Pune
2
@SachinfromPune po prostu dodaj SET FOREIGN_KEY_CHECKS = 0; na początku pliku mysql i SET FOREIGN_KEY_CHECKS = 1; na końcu pliku mysql, reimport danych
inrsaurabh
1
Czy to nie jest problematyczne? Tracisz integralność referencyjną, prawda?
roadrunner66
Więzy integralności są wspierane przez obecność poprawnych wpisów indeksu. Tak długo, jak masz prawidłowe klucze i indeksy, powinieneś być w stanie wyłączyć sprawdzanie klucza podczas wprowadzania zbiorczego.
Vernon Keenan
46

Odkryłem inny dziwny przypadek: jeśli przypadkowo utworzysz klucz obcy z tabeli InnoDB do tabeli MyISAM, MySQL zgłasza ten błąd podczas wstawiania, nawet jeśli dane są prawidłowe.

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

NickZoic
źródło
1
Tak, mam ten sam problem. Dwie tabele powinny być InnoDB!
emeraldhieu
2
Miałem ten sam problem, dzięki za cynk. Tutaj jest łącze do dokumentacji MySQL na temat konwertowania tabel z MyISAM do InnoDB dev.mysql.com/doc/refman/5.7/en/ ... TLDR: ALTER TABLE nazwa_tabeli ENGINE = InnoDB;
Guilherme Vaz
Rzeczywiście tak było w mojej bazie danych. Postanowiłem zmienić silnik MyISAM na InnoDB. Wreszcie mogę pracować z bazą danych tak, jak chciałem.
Mike
17

Otrzymujesz ten błąd, ponieważ istnieje pewna wartość int, table2.UserIDktóra nie istnieje table1.UserID( wydaje mi się, że ustawiłeś table2.UserIDwartość ręcznie przed utworzeniem tego klucza obcego).
Jeden przykład dla tej sceny: table1.UserIDpobierz wartości 1,2,3 i table2.UserIDuzyskaj wartości 4 (dodaj ręcznie). Więc kiedy tworzysz klucz obcy, nie mogą znaleźć UserID = 4z table1i wystąpi błąd.
Aby naprawić ten błąd, po prostu usuń UserID = 4z table2lub możesz opróżnić oba z nich, a następnie utwórz klucz obcy i.
Powodzenia!

Justin
źródło
11

Zajęło mi to trochę czasu, zanim zrozumiałem. Mówiąc najprościej, tabela, która odwołuje się do drugiej tabeli, zawiera już dane, a co najmniej jedna z jej wartości nie istnieje w tabeli nadrzędnej.

np. Tabela 2 zawiera następujące dane:

UserID    PostID    Title    Summary
5         1         Lorem    Ipsum dolor sit

Tabela 1

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

Jeśli spróbujesz ZMIENIĆ tabelę2 i dodać klucz obcy, zapytanie nie powiedzie się, ponieważ identyfikator UserID = 5 nie istnieje w tabeli1.

Sbudah
źródło
10

Jeśli wstawiłeś wiersz do tabeli 1 przed utworzeniem klucza obcego w tabeli 2, otrzymasz błąd ograniczenia klucza obcego, ponieważ wartość automatycznego przyrostu wynosi 2 w tabeli 1 i 1 w tabeli 2. Aby rozwiązać ten problem, musisz obetnij tabelę 1 i ustaw wartość automatycznego zwiększania z powrotem na 1. Następnie możesz dodać tabelę 2.

Attaque
źródło
10

Upewnij się, że ustawiłeś silnik bazy danych na InnoDB, ponieważ w MyISAM klucz obcy i transakcje nie są obsługiwane

Aman Maurya
źródło
2
ALTER TABLE my_table ENGINE = InnoDB;
Bishwas Mishra
7

Tylko mała poprawka: ustaw wartość JoinColumn jako „nullable = true” w tabeli 1 i pole „UserID” „insertable = false” i „nullable = true” w tabeli 2.

W jednostce tabeli 1:

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

W jednostce tabeli 2:

@Column(insertable = false, nullable = true)
private int UserID;
Ujjwal Chaudhary
źródło
Ta odpowiedź całkowicie rozwiązała mój problem, bardzo dziękuję za udostępnienie tego. Kluczem dla mnie było dodanie @Column (insertable = false, nullable = true) w polu, którego używam jako klucza foraeing w moim obiekcie / tabeli podrzędnej.
Israelm
6

Miałem ten sam problem, rozwiązanie jest łatwe.

Próbujesz dodać identyfikator w tabeli podrzędnej, który nie istnieje w tabeli nadrzędnej.

sprawdź dobrze, ponieważ InnoDB ma błąd, który czasami zwiększa kolumnę auto_increment bez dodawania wartości, na przykład INSERT ... ON DUPLICATE KEY

Blaztix
źródło
poważnie? nie wstawiaj identyfikatora, który nie istnieje ... po prostu sprawdź
Blaztix
5

Miałem podobny problem. Próbujesz zastosować klucz obcy do tabeli, która ma zawartość, a kolumna nie dopuszcza wartości null. Masz dwie możliwości.

  1. Spraw, aby kolumna, do której chcesz zastosować ograniczenia klucza obcego, miała wartość null. W ten sposób klucz obcy zostanie zastosowany, wiedząc, że niektóre pola mogą mieć wartość null. ( To właśnie zrobiłem. )
  2. Utwórz kolumnę, do której chcesz zastosować ograniczenie klucza obcego, napisz zapytanie, aby wstawić klucz obcy do kolumny, a następnie zastosuj ograniczenia klucza obcego. ( Nie próbowałem tego, ale powinno działać )
Jakub
źródło
4

Upewnij się, że wartość wstawiana do klucza obcego istnieje w tabeli nadrzędnej. To mi pomogło. Na przykład, jeśli wstawisz user_id = 2do table.2, ale table.1nie masz a user_id = 2, wówczas ograniczenie zwróci błąd. Dokładnie mówiąc, mój kod błędu to 1452. Mam nadzieję, że pomoże to komukolwiek innemu z tym samym problemem!

Dustin Hammack
źródło
3

Miałem ten sam problem, a powodem było to, że przed dodaniem klucza obcego miałem wiersz w pierwszej tabeli.

Ouissal
źródło
1

Napotkałem również ten sam problem, a problem polegał na tym, że wartość moich wpisów w tabeli nadrzędnej nie była zgodna z wartością tabeli klucza obcego. Więc spróbuj po wyczyszczeniu wszystkich wierszy.

Justin Jose
źródło
Ograniczenie wymaga, aby użytkownicy, do których odwołuje się tabela 2, byli już zdefiniowani w tabeli 1.
sorak
1

W przypadku, gdy rozwiązania dostarczone przez innych nie zadziałały. Następnie powinieneś spróbować sprawdzić silniki bazy danych tabel nadrzędnych i podrzędnych. W moim przypadku silnik tabel nadrzędnych był ustawiony na „MyISAM”, zmieniając go na InnoDB, naprawił to.

Mam nadzieję, że pomoże to innym, którzy utknęli tak jak ja.

Arun Shankar
źródło
1

Nie należy umieszczać pola ondelete przeciwko kaskadzie w bazie danych.

Ustaw więc pole onDelete na RESTRICT

Powodzenia ♥

HamidReza Biglari
źródło
0

Kolejny dziwny przypadek, który spowodował ten błąd. Błędnie odniosłem moje klucze obce do klucza podstawowego id. Było to spowodowane niepoprawnymi poleceniami alter table. Dowiedziałem się tego, przeszukując tabelę INFORMATION_SCHEMA (zobacz tę odpowiedź stackoverflow)

Tabela była tak zagmatwana, że ​​nie można jej było naprawić żadnymi poleceniami ALTER TABLE . W końcu upuściłem stół i zrekonstruowałem go. Pozbyło się błędu integrityError.

Vicky T.
źródło
0

Może podczas dodawania userIDkolumny istnieją dane dla tej określonej tabeli, która została utworzona, więc będzie miała domyślną wartość 0, spróbuj dodać kolumnę bezNOT NULL

WTFZane
źródło
0

Pojawił się również ten błąd: „Nie można dodać lub zaktualizować wiersza podrzędnego: nie udało się ograniczyć klucza obcego”. Wystąpił błąd podczas dodawania nowego wiersza do tabeli nadrzędnej

Problem polegał na tym, że ograniczenie klucza obcego zostało zdefiniowane w tabeli nadrzędnej zamiast tabeli podrzędnej.

Nadir Latif
źródło
0

Jeśli używasz indeksu mysql lub relacji między tabelami, najpierw usuń kolumny (na przykład: city_id) i utwórz nowe kolumny o tej samej nazwie (na przykład: city_id), a następnie spróbuj ponownie ...

Mahmut Aydın
źródło
0

Czy istnieją jakieś dane, które zawiera tabela? Jeśli tak, spróbuj wyczyścić wszystkie dane z tabeli, do której chcesz dodać klucz obcy. Następnie ponownie uruchom kod (dodaj klucz obcy).

Tyle razy napotkałem ten problem. To wyczyszczenie wszystkich danych w tabeli działa, gdy chcesz dodać klucz obcy do istniejącej tabeli.

Mam nadzieję, że to zadziała :)

Noldy
źródło
0

Usuń indeksy pola ID użytkownika w tabeli 2. Dla mnie pasuje

Anton
źródło
0

Ten błąd występuje, gdy chcesz dodać klucz obcy z wartościami, które nie istnieją w kluczu podstawowym tabeli nadrzędnej. Należy się upewnić, że nowy identyfikator użytkownika klucza obcego w tabeli 2 ma wartości, które istnieją w kluczu podstawowym tabela1, czasami domyślnie jest to null lub równe 0.

Możesz najpierw zaktualizować wszystkie pola klucza obcego w tabeli 2 o wartość istniejącą w kluczu podstawowym tabeli 1.

update table2 set UserID = 1 where UserID is null

Jeśli chcesz dodać różne identyfikatory użytkowników, musisz zmodyfikować każdy wiersz z żądanymi wartościami.

Vladimir Salguero
źródło
-1

Niepowodzenie ograniczenia klucza obcego tabeli podrzędnej

Ten problem może wystąpić z następującego powodu:

Jeśli robisz to w Spring mvc, musisz wyraźnie opisać typ identyfikatora, ponieważ czasami mysql nie rozpoznaje typu identyfikatora. więc jawnie ustawiasz tak, jak w obu tabelach w klasie jednostki@GeneratedValue (strategy = GenerationType.IDENTITY)

Qaiser Iqbal Moeeni
źródło