Внешний ключ добавляет сбой в MySQL с кодом ошибки 1005, номер 150

Итак, я пытаюсь добавить новый внешний ключ в одну из моих таблиц:

 ALTER TABLE `UserTransactions`.`ExpenseBackTransactions` 
   ADD CONSTRAINT `FK_EBTx_CustomAccountID`
   FOREIGN KEY (`CustomAccountID` )
   REFERENCES `UserTransactions`.`CustomAccounts` (`CustomAccountID`)
   ON DELETE NO ACTION
   ON UPDATE NO ACTION,
   ADD INDEX `FK_EBTx_CustomAccountID` (`CustomAccountID` ASC) ;

и я получаю следующую ошибку:

Error Code: 1005
Can't create table './UserTransactions/#sql-187a_29.frm' (errno: 150)

В прошлом я сделал несколько изменений в этой и других таблицах, и это первый случай, когда я столкнулся с этой проблемой. Любые идеи, что вызывает это?

UPDATE

Моя ошибка SHOW INNODB STATUS:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
110525 15:56:36 Error in foreign key constraint of table UserTransactions/#sql-187a_2c:

  FOREIGN KEY (`CustomAccountID` )
  REFERENCES `UserTransactions`.`CustomAccounts` (`CustomAccountID` )
  ON DELETE NO ACTION
  ON UPDATE NO ACTION
, ADD INDEX `FK_EBTx_CustomAccountID` (`CustomAccountID` ASC):
Cannot resolve table name close to:
 (`CustomAccountID` )
  ON DELETE NO ACTION
  ON UPDATE NO ACTION
, ADD INDEX `FK_EBTx_CustomAccountID` (`CustomAccountID` ASC)

Ответы

Ответ 1

Здесь хороший контрольный список.

Ниже приведен список известных причин, по которым люди сообщили о страшном errno 150:

  • Тип и/или размер двух ключевых полей не являются точным совпадением. Например, если один из INT (10), ключевое поле также должно быть INT (10), а не INT (11) или TINYINT. Вы можете подтвердить размер поля, используя SHOW CREATE TABLE, потому что браузер запросов иногда визуально показывает только INTEGER для INT (10) и INT (11). Вы также должны проверить, что он НЕ ПОДПИСАЛ, а другой НЕ ПОДКЛЮЧЕН. Оба они должны быть точно такими же. (Подробнее о подписанных vs без знака здесь).
  • В одном из ключевых полей, которые вы пытаетесь ссылаться, нет индекса и/или не является первичным ключом. Если одно из полей отношения не является первичным ключом, вы должны создать индекс для этого поля. (благодаря Venkatesh и Erichero и Terminal Incoherent для этого совета).
  • Имя внешнего ключа является дубликатом уже существующего ключа. Убедитесь, что имя вашего внешнего ключа уникально в вашей базе данных. Просто добавьте несколько случайных символов в конец вашего имени ключа, чтобы проверить это. (Спасибо Нильсу за этот совет)
  • Одна или обе ваши таблицы - таблица MyISAM. Чтобы использовать внешние ключи, таблицы должны быть как InnoDB. (На самом деле, если обе таблицы являются MyISAM, тогда вы не получите сообщение об ошибке - он просто не создаст ключ.) В Query Browser вы можете указать тип таблицы.
  • Вы указали каскад ON DELETE SET NULL, но для соответствующего поля ключа установлено значение NOT NULL. Вы можете исправить это, изменив свой каскад или установив поле, чтобы разрешить значения NULL. (Спасибо Сэмми и Дж. Джаммину)
  • Убедитесь, что параметры Charset и Collate одинаковы как на уровне таблицы, так и на отдельном поле для ключевых столбцов. (Спасибо FRR за этот совет)
  • У вас есть значение по умолчанию (т.е. по умолчанию = 0) в столбце внешнего ключа (спасибо Omar за подсказку)
  • Одно из полей отношения является частью комбинационного (составного) ключа и не имеет собственного индивидуального индекса. Несмотря на то, что поле имеет индекс как составную часть составного ключа, вы должны создать отдельный индекс только для этого ключевого поля, чтобы использовать его в ограничении. (Спасибо Алексу за этот совет)
  • У вас есть синтаксическая ошибка в вашем заявлении ALTER или вы ошибочно указали одно из имен полей в отношениях (спасибо Кристиану и Матео за подсказку)
  • Имя вашего внешнего ключа превышает максимальную длину 64 символа. (Спасибо Nyleta за подсказку)

Ответ 2

По моему опыту, errno: 150 обычно указывает, что типы данных столбца FOREIGN KEY в таблице ключей и соответствующей таблице не идентичны. Убедитесь, что CustomAccounts.CustomAccountID и ExpenseBackTransactions.CustomAccountID - это тот же самый тип, включая UNSIGNED, если он применяется.

Если это не поможет, отправьте SHOW CREATE TABLE ExpenseBackTransactions; и SHOW CREATE TABLE CustomAccounts;

Ответ 3

Поймать 22. Иностранным ключам нужны индексы. MySQL не заказывает этот запрос, чтобы индекс существовал во время проверки внешнего ключа. Таким образом, сначала создайте индекс, затем добавьте внешний ключ в 2 отдельных запроса.