Miałem ten sam problem z ALTER TABLE ADD FOREIGN KEY
.
Po godzinie stwierdziłem, że te warunki muszą być spełnione, aby nie pojawił się błąd 150:
-
Tabela nadrzędna musi istnieć przed zdefiniowaniem klucza obcego, do którego będzie się odwoływać. Musisz zdefiniować tabele we właściwej kolejności:najpierw tabela nadrzędna, a następnie tabela potomna. Jeśli obie tabele odwołują się do siebie nawzajem, musisz utworzyć jedną tabelę bez ograniczeń FK, następnie utworzyć drugą tabelę, a następnie dodać ograniczenie FK do pierwszej tabeli za pomocą
ALTER TABLE
. -
Obie tabele muszą obsługiwać ograniczenia klucza obcego, tj.
ENGINE=InnoDB
. Inne silniki pamięci masowej po cichu ignorują definicje kluczy obcych, więc nie zwracają żadnego błędu ani ostrzeżenia, ale ograniczenie FK nie jest zapisywane. -
Kolumny, do których istnieją odwołania w tabeli nadrzędnej, muszą być kolumnami z lewej strony klucza. Najlepiej, jeśli klucz w Rodzic to
PRIMARY KEY
lubUNIQUE KEY
. -
Definicja FK musi odwoływać się do kolumny (kolumn) PK w tej samej kolejności, co definicja PK. Na przykład, jeśli FK
REFERENCES Parent(a,b,c)
to PK Rodzica nie może być zdefiniowane w kolumnach w kolejności(a,c,b)
. -
Kolumny PK w tabeli Parent muszą być tego samego typu danych co kolumny FK w tabeli Child. Na przykład, jeśli kolumna PK w tabeli nadrzędnej to
UNSIGNED
, pamiętaj, aby zdefiniowaćUNSIGNED
dla odpowiedniej kolumny w polu Tabela podrzędna.Wyjątek:długość ciągów może być inna. Na przykład
VARCHAR(10)
może odwoływać się doVARCHAR(20)
lub odwrotnie. -
Wszelkie kolumny FK typu ciąg muszą mieć ten sam zestaw znaków i sortowanie, co odpowiadające im kolumny PK.
-
Jeśli w tabeli podrzędnej znajdują się już dane, każda wartość w kolumnach FK musi odpowiadać wartości w kolumnach PK tabeli nadrzędnej. Sprawdź to za pomocą zapytania takiego jak:
SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK WHERE Parent.PK IS NULL;
Musi to zwrócić zero (0) niedopasowanych wartości. Oczywiście to zapytanie jest ogólnym przykładem; musisz zastąpić nazwy tabel i nazwy kolumn.
-
Ani tabela nadrzędna, ani tabela podrzędna nie mogą być tabelą
TEMPORARY
tabela. -
Ani tabela nadrzędna, ani tabela podrzędna nie mogą być
PARTITIONED
tabela. -
Jeśli zadeklarujesz FK z
ON DELETE SET NULL
opcja, to kolumny FK muszą mieć wartość null. -
Jeśli zadeklarujesz nazwę ograniczenia dla klucza obcego, nazwa ograniczenia musi być unikalna w całym schemacie, a nie tylko w tabeli, w której jest zdefiniowane ograniczenie. Dwie tabele mogą nie mieć własnych ograniczeń o tej samej nazwie.
-
Jeśli w innych tabelach znajdują się inne FK wskazujące na to samo pole, dla którego próbujesz utworzyć nowy FK, i są one zniekształcone (tj. różne sortowanie), należy je najpierw ujednolicić. Może to być wynikiem wcześniejszych zmian, gdzie
SET FOREIGN_KEY_CHECKS = 0;
został wykorzystany z niespójną relacją zdefiniowaną przez pomyłkę. Zobacz odpowiedź @andrewdotn poniżej, aby uzyskać instrukcje, jak zidentyfikować te problemy FK.
Mam nadzieję, że to pomoże.