MySQL nie może utworzyć ograniczenia klucza obcego

87

Mam problemy z utworzeniem klucza obcego do istniejącej tabeli w bazie danych mysql.

Mam stolik exp:

+-------------+------------------+------+-----+---------+-------+
| Field       | Type             | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| EID         | varchar(45)      | NO   | PRI | NULL    |       |
| Comment     | text             | YES  |     | NULL    |       |
| Initials    | varchar(255)     | NO   |     | NULL    |       |
| ExpDate     | date             | NO   |     | NULL    |       |
| InsertDate  | date             | NO   |     | NULL    |       |
| inserted_by | int(11) unsigned | YES  | MUL | NULL    |       |
+-------------+------------------+------+-----+---------+-------+

i nie chcę utworzyć nowej tabeli o nazwie sample_dfodwołującej się do tego, używając następującego:

CREATE TABLE sample_df (
df_id mediumint(5) unsigned AUTO_INCREMENT primary key,
sample_type mediumint(5) unsigned NOT NULL,
df_10 BOOLEAN NOT NULL,
df_100 BOOLEAN NOT NULL,
df_1000 BOOLEAN NOT NULL,
df_above_1000 BOOLEAN NOT NULL,
target INT(11) unsigned NOT NULL,
assay MEDIUMINT(5) unsigned zerofill NOT NULL,
insert_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
inserted_by INT(11) unsigned NOT NULL,
initials varchar(255),
experiment VARCHAR(45),
CONSTRAINT FOREIGN KEY (inserted_by) REFERENCES user (iduser),
CONSTRAINT FOREIGN KEY (target) REFERENCES protein (PID),
CONSTRAINT FOREIGN KEY (sample_type) REFERENCES sample_type (ID),
CONSTRAINT FOREIGN KEY (assay) REFERENCES assays (AID),
CONSTRAINT FOREIGN KEY (experiment) REFERENCES exp (EID)
);

Ale pojawia się błąd:

ERROR 1215 (HY000): Cannot add foreign key constraint

Aby uzyskać więcej informacji, zrobiłem:

SHOW ENGINE INNODB STATUS\G

Od którego dostałem:

FOREIGN KEY (experiment) REFERENCES exp (EID)
):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.

Wydaje mi się, że typy kolumn wydają się pasować, ponieważ oba są varchar (45). (Próbowałem też ustawić experimentkolumnę na wartość niezerową, ale to nie rozwiązało problemu) Więc myślę, że problem musi być taki Cannot find an index in the referenced table where the referenced columns appear as the first columns. Ale nie jestem do końca pewien, co to oznacza, ani jak to sprawdzić / naprawić. Czy ktoś ma jakieś sugestie? A co to znaczy first columns?

numfar
źródło
11
Nigdzie w żadnej odpowiedzi ani pytaniu nie byłem w stanie stwierdzić, że ten błąd może wystąpić z powodu różnicy w zestawie znaków. Dzięki .. Pozdrawiam !!!
proprius
3
Sprawdź również dwukrotnie sortowanie kolumn. Twoja tabela może być utf8mb4, ale kolumna może mieć inne sortowanie!
Watson,
@Watson charset w moim przypadku, ale otrzymujesz mój głos za skłonienie mnie do myślenia.
user2910265

Odpowiedzi:

155

Po prostu wrzucając to do mieszanki możliwych przyczyn, natknąłem się na to, gdy kolumna tabeli odniesienia miała ten sam „typ”, ale nie miała tego samego podpisu.

W moim przypadku kolumna tabeli, do której się odwołujemy, to TINYINT UNSIGNED, a moja kolumna tabeli odniesienia to TINYINT SIGNED. Wyrównanie obu kolumn rozwiązało problem.

Austen Hoogen
źródło
2
Rozwiązanie zaproponowane przez @ austen-hoogen rozwiązało mój problem. Jednak z powodu niskiej reputacji nie mogę głosować ani komentować jego rozwiązania. W moim przypadku kluczem podstawowym była liczba całkowita, automatyczna inkrementacja i brak znaku. Ale klucz obcy (kolumna tabeli odwołań) był typem podpisanym. Zmieniłem go na niepodpisany i mogłem pomyślnie stworzyć relację.
Bal Singh,
Tak, przeszedł ten sam problem. Moim kluczem głównym był BIGINT (20), a moim przywołanym kluczem w innej tabeli był INT (10) bez znaku. musimy się upewnić, że wszystkie pasują. to znaczy. BIGINT (20), aw tabeli, do której się odwołujemy, powinno być również BIGINT (20)
Manjunath Reddy
Dziękuję Ci! To rozwiązanie rozwiązało również mój problem! Miałem intw tabeli, w której planowałem ustawić klucz obcy i bigint w drugiej tabeli.
Aleksej_Shherbak
38

Ten błąd może również wystąpić, jeśli tabela odwołań i bieżąca tabela nie mają tego samego zestawu znaków.

Pratik Singhal
źródło
3
Po ustawieniu zestawu znaków jak latinw przywołanej tabeli, po 3 godzinach ponownie zacząłem oddychać.
Abhishek Kamal
Dziękuję Ci. To nie jest trywialny problem
Ventoh
24

Według http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html

MySQL wymaga indeksów kluczy obcych i kluczy, do których istnieją odniesienia, aby sprawdzanie kluczy obcych było szybkie i nie wymagało skanowania tabeli. W tabeli odwołań musi istnieć indeks, w którym kolumny klucza obcego są wymienione jako pierwsze kolumny w tej samej kolejności.

InnoDB pozwala kluczowi obcemu odwoływać się do dowolnej kolumny indeksu lub grupy kolumn. Jednak w tabeli, do której istnieje odwołanie, musi istnieć indeks, w którym kolumny, do których istnieją odwołania, są wymienione jako pierwsze kolumny w tej samej kolejności.

Jeśli więc indeks w tabeli, do której się odwołujemy, istnieje i składa się z kilku kolumn, a żądana kolumna nie jest pierwsza, wystąpi błąd.

Przyczyną naszego błędu było naruszenie następującej reguły:

Odpowiednie kolumny w kluczu obcym i przywoływanym kluczu muszą mieć podobne typy danych. Rozmiar i znak typów całkowitych muszą być takie same. Długość typów strun nie musi być taka sama. W przypadku kolumn z ciągami niebinarnymi (znakowymi) zestaw znaków i sortowanie muszą być takie same.

Anton
źródło
20

Jak wspomniano @Anton, może to być spowodowane innym typem danych. W moim przypadku miałem klucz główny BIGINT (20) i próbowałem ustawić klawisz foreight z INT (10)

antongorodezkiy
źródło
2
Dziękuję Ci! Podobny problem, gdy używałem INT (11) z INT (11), ale jeden był kluczem podstawowym i dlatego był niepodpisany, podczas gdy drugi był podpisany!
Michael Scott Cuthbert
@MichaelScottCuthbert Same
Germa Vinsmoke
7

Mój problem dotyczył sortowania między tabelą, do której się odwołujesz, a tabelą do utworzenia, więc musiałem jawnie ustawić typ sortowania klucza, do którego się odwoływałem.

  • Najpierw uruchomiłem zapytanie w tabeli, do której się odwołano, aby uzyskać typ sortowania
show table STATUS like '<table_name_here>';
  • Następnie skopiowałem typ sortowania i wyraźnie określiłem typ sortowania Employer_id w kwerendzie tworzenia. W moim przypadku był to utf8_general_ci
CREATE TABLE dbo.sample_db
(
  id INT PRIMARY KEY AUTO_INCREMENT,
  event_id INT SIGNED NOT NULL,
  employee_id varchar(45) COLLATE utf8_general_ci NOT NULL,
  event_date_time DATETIME,
  CONSTRAINT sample_db_event_event_id_fk FOREIGN KEY (event_id) REFERENCES event (event_id),
  CONSTRAINT sample_db_employee_employee_id_fk FOREIGN KEY (employee_id) REFERENCES employee (employee_id)
);
user11891461
źródło
2

Dokładna kolejność klucz podstawowy musi również dopasować bez dodatkowych kolumn pomiędzy.

Miałem konfigurację klucza podstawowego, w której kolejność kolumn faktycznie pasuje, ale problem polegał na tym, że klucz podstawowy miał dodatkową kolumnę, która nie jest częścią klucza obcego tabeli odwołań

np. tabela 2, kolumna (a, b, c) -> tabela 1, kolumna (a, b, d, c) - TO NIEPOWODZENIA

Musiałem zmienić kolejność kolumn klucza podstawowego, aby nie tylko były uporządkowane w ten sam sposób, ale nie miały dodatkowych kolumn w środku:

np. tabela 2, kolumna (a, b, c) -> tabela 1, kolumna (a, b, c, d) - TO SUKCES

Nelson
źródło
2

W niektórych przypadkach, poza zdefiniowaniem go jako klucza podstawowego, musiałem uczynić przywoływane pole unikalnym.

Ale odkryłem, że nie zdefiniowanie go jako unikalnego nie stwarza problemu w każdym przypadku. Nie mogłem jednak rozgryźć scenariuszy. Prawdopodobnie ma to związek z definicją dopuszczającą wartość zerową.

sprksh
źródło
Czy przeczytałeś wprowadzenie do ZK lub instrukcję? FK odwołuje się do UNIQUE; PK oznacza UNIQUE NOT NULL.
philipxy
2

W moim przypadku został utworzony za pomocą liczby całkowitej dla identyfikatora, a tablica referencyjna tworzyła domyślnie klucz obcy za pomocą biginta .

Spowodowało to wielki koszmar w mojej aplikacji Rails, ponieważ migracja nie powiodła się, ale pola zostały utworzone w DB, więc pojawiły się w DB, ale nie w schemacie aplikacji Rails.

helenatxu
źródło
1

Odwołanie się do tej samej kolumny więcej niż raz w tym samym ograniczeniu również powoduje ten Cannot find an index in the referenced tablebłąd, ale może być trudny do wykrycia w dużych tabelach. Podziel ograniczenia i zadziała zgodnie z oczekiwaniami.

Edward
źródło
1

Miałem też ten błąd. Żadna z odpowiedzi nie dotyczyła mnie. W moim przypadku mój GUI automatycznie tworzy tabelę z podstawowym unikalnym identyfikatorem jako „nieprzypisany”. Nie udaje się to, gdy próbuję utworzyć klucz obcy i powoduje dokładnie ten sam błąd. Mój klucz główny musi zostać przypisany.

Jeśli napiszesz sam SQL w ten sposób id int unique auto_increment , nie masz tego problemu, ale z jakiegoś powodu robi to mój GUI id int unassigned unique auto_increment.

Mam nadzieję, że to pomoże komuś innemu w dalszej drodze.

Paul Carlton
źródło
1

Dla mnie był to tylko zestaw znaków i zestawienie DB. Zmieniłem na utf8_unicode_ci i działa

Diego Herrera
źródło
1
Czy możesz dołączyć przykład, jak sprawdzić bieżący zestaw znaków / sortowanie?
thelr