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.


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ę.


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.


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.


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/


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!


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.


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.


10

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


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;

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


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

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!


3

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


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.


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.


1

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

Ustaw więc pole onDelete na RESTRICT

Powodzenia ♥


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.


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


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.


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 ...


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


0

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


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.


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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.