Měl jsem stejný problém s ALTER TABLE ADD FOREIGN KEY
.
Po hodině jsem zjistil, že tyto podmínky musí být splněny, aby se neobjevila chyba 150:
-
Nadřazená tabulka musí existovat předtím, než definujete cizí klíč, abyste na ni odkazovali. Tabulky musíte definovat ve správném pořadí:Nejprve nadřazená tabulka, potom podřízená tabulka. Pokud na sebe obě tabulky odkazují, musíte vytvořit jednu tabulku bez omezení FK, poté vytvořit druhou tabulku a poté přidat omezení FK do první tabulky pomocí
ALTER TABLE
. -
Obě tabulky musí podporovat omezení cizího klíče, tj.
ENGINE=InnoDB
. Jiné úložné stroje tiše ignorují definice cizích klíčů, takže nevrací žádnou chybu ani varování, ale omezení FK se neuloží. -
Odkazované sloupce v nadřazené tabulce musí být sloupce klíče zcela vlevo. Nejlepší je, když je klíč v Parentu
PRIMARY KEY
neboUNIQUE KEY
. -
Definice FK musí odkazovat na sloupec (sloupce) PK ve stejném pořadí jako definice PK. Například pokud FK
REFERENCES Parent(a,b,c)
pak rodičovská PK nesmí být definována ve sloupcích v pořadí(a,c,b)
. -
Sloupce PK v nadřazené tabulce musí mít stejný datový typ jako sloupce FK v podřízené tabulce. Pokud je například sloupec PK v nadřazené tabulce
UNSIGNED
, nezapomeňte definovatUNSIGNED
pro odpovídající sloupec v poli Child table.Výjimka:délka řetězců se může lišit. Například
VARCHAR(10)
může odkazovat naVARCHAR(20)
nebo naopak. -
Všechny sloupce FK typu řetězce musí mít stejnou znakovou sadu a řazení jako odpovídající sloupce PK.
-
Pokud již v podřízené tabulce jsou data, musí se každá hodnota ve sloupci FK shodovat s hodnotou ve sloupci PK nadřazené tabulky. Zkontrolujte to pomocí dotazu jako:
SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK WHERE Parent.PK IS NULL;
To musí vrátit nulové (0) neshodné hodnoty. Je zřejmé, že tento dotaz je obecný příklad; musíte nahradit názvy tabulek a názvy sloupců.
-
Nadřazená ani podřízená tabulka nemohou být
TEMPORARY
tabulka. -
Nadřazená ani podřízená tabulka nemohou být
PARTITIONED
tabulka. -
Pokud deklarujete FK pomocí
ON DELETE SET NULL
pak musí mít sloupce FK hodnotu null. -
Pokud deklarujete název omezení pro cizí klíč, musí být název omezení jedinečný v celém schématu, nejen v tabulce, ve které je omezení definováno. Dvě tabulky nemusí mít vlastní omezení se stejným názvem.
-
Pokud jsou v jiných tabulkách nějaké další FK ukazující na stejné pole, pro které se pokoušíte vytvořit nový FK, a mají nesprávný formát (tj. jiné řazení), bude nutné je nejprve uvést do souladu. Může to být důsledek minulých změn, kde
SET FOREIGN_KEY_CHECKS = 0;
byl použit s nekonzistentním vztahem definovaným omylem. Viz odpověď @andrewdotn níže pro pokyny, jak identifikovat tyto problémové FK.
Doufám, že to pomůže.