Имах същия проблем с ALTER TABLE ADD FOREIGN KEY
.
След един час установих, че тези условия трябва да бъдат изпълнени, за да не се получи грешка 150:
-
Родителската таблица трябва да съществува, преди да дефинирате външен ключ, за да я препратите. Трябва да дефинирате таблиците в правилния ред:първо родителска таблица, след това дъщерна таблица. Ако и двете таблици се позовават една на друга, трябва да създадете една таблица без FK ограничения, след това да създадете втората таблица, след което да добавите FK ограничението към първата таблица с
ALTER TABLE
. -
И двете таблици трябва да поддържат ограничения на външния ключ, т.е.
ENGINE=InnoDB
. Други механизми за съхранение безшумно игнорират дефинициите на външни ключове, така че не връщат грешка или предупреждение, но FK ограничението не се запазва. -
Референтните колони в родителската таблица трябва да са най-лявата колона на ключ. Най-добре е ключът в родителския елемент да е
PRIMARY KEY
илиUNIQUE KEY
. -
Дефиницията на FK трябва да препраща към колоната(ите) на PK в същия ред като дефиницията на PK. Например, ако FK
REFERENCES Parent(a,b,c)
тогава PK на родителя не трябва да се дефинира в колони в ред(a,c,b)
. -
PK колоната(ите) в родителската таблица трябва да бъде от същия тип данни като колоната(ите) на FK в дъщерната таблица. Например, ако PK колона в родителската таблица е
UNSIGNED
, не забравяйте да дефиниратеUNSIGNED
за съответната колона в полето Child table.Изключение:дължината на низовете може да е различна. Например,
VARCHAR(10)
може да се позовава наVARCHAR(20)
или обратно. -
Всяка колона(и) на FK от низов тип трябва да има същия набор от знаци и съпоставяне като съответната(ите) PK колона(и).
-
Ако вече има данни в дъщерната таблица, всяка стойност в колоната(ите) на FK трябва да съответства на стойност в колоната(ите) на родителската таблица PK. Проверете това със заявка като:
SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK WHERE Parent.PK IS NULL;
Това трябва да върне нула (0) несъвпадащи стойности. Очевидно тази заявка е общ пример; трябва да замените имената на вашите таблици и колони.
-
Нито таблицата Родител, нито таблицата Дъще могат да бъдат
TEMPORARY
таблица. -
Нито таблицата Родител, нито таблицата Дъще могат да бъдат
PARTITIONED
таблица. -
Ако декларирате FK с
ON DELETE SET NULL
опция, тогава колоната(ите) на FK трябва да бъде нула. -
Ако декларирате име на ограничение за външен ключ, името на ограничението трябва да бъде уникално в цялата схема, а не само в таблицата, в която е дефинирано ограничението. Две таблици може да нямат собствено ограничение със същото име.
-
Ако има други FK в други таблици, сочещи към същото поле, за което се опитвате да създадете новия FK, и те са неправилно оформени (т.е. различно съпоставяне), те първо трябва да бъдат съгласувани. Това може да е резултат от минали промени, където
SET FOREIGN_KEY_CHECKS = 0;
е използвано с непоследователна връзка, дефинирана по погрешка. Вижте отговора на @andrewdot по-долу за инструкции как да идентифицирате тези проблемни FK.
Надявам се това да помогне.