Ошибка внешнего ключа MySQL 1005 errno 150

Я делаю небольшую базу данных с MySQL Workbench. У меня есть главная таблица, называемая "Immobili", которая имеет первичный ключ, состоящий из четырех столбцов: (Comune, Via, Civico, Immobile).

теперь у меня также есть три другие таблицы, которые имеют тот же первичный ключ (Comune, Via, Civico, Immobile), но эти поля также ссылаются на таблицу Immobili.

первый вопрос: Могу ли я сделать первичный ключ, который также является внешним ключом?

второй вопрос: когда я пытаюсь экспорт изменений говорит: Выполнение SQL скрипта в server

# ERROR: Error 1005: Can't create table 'dbimmobili.condoni' (errno: 150)

CREATE  TABLE IF NOT EXISTS `dbimmobili`.`Condoni` (

  `ComuneImmobile` VARCHAR(50) NOT NULL ,
  `ViaImmobile` VARCHAR(50) NOT NULL ,
  `CivicoImmobile` VARCHAR(5) NOT NULL ,
  `InternoImmobile` VARCHAR(3) NOT NULL ,
  `ProtocolloNumero` VARCHAR(15) NULL ,
  `DataRichiestaSanatoria` DATE NULL ,
  `DataSanatoria` DATE NULL ,
  `SullePartiEsclusive` TINYINT(1) NULL ,
  `SullePartiComuni` TINYINT(1) NULL ,
  `OblazioneInEuro` DOUBLE NULL ,
  `TecnicoOblazione` VARCHAR(45) NULL ,
  `TelefonoTecnico` VARCHAR(15) NULL ,
  INDEX `ComuneImmobile` (`ComuneImmobile` ASC) ,
  INDEX `ViaImmobile` (`ViaImmobile` ASC) ,
  INDEX `CivicoImmobile` (`CivicoImmobile` ASC) ,
  INDEX `InternoImmobile` (`InternoImmobile` ASC) ,

  PRIMARY KEY (`ComuneImmobile`, `ViaImmobile`, `CivicoImmobile`, `InternoImmobile`) ,

  CONSTRAINT `ComuneImmobile`
    FOREIGN KEY (`ComuneImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`ComuneImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT `ViaImmobile`
    FOREIGN KEY (`ViaImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`ViaImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT `CivicoImmobile`
    FOREIGN KEY (`CivicoImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`CivicoImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT `InternoImmobile`
    FOREIGN KEY (`InternoImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`InternoImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE
) ENGINE = InnoDB

отображение состояния двигателя:

ошибка ограничения внешнего ключа таблицы dbimmobili / valutazionimercato:

Не удается найти индекс в ссылочной таблице, где ссылочные столбцы отображаются как первые столбцы, или типов столбцов в таблице и таблицы не совпадают для ограничения. Обратите внимание, что тип внутренней памяти ENUM и SET изменился в таблицы, созданные с помощью >= InnoDB-4.1.12, и такие столбцы в старых таблицах не могут ссылаться на такие столбцы в новых таблицах.

где я делаю неправильно?

17 ответов


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

тест:

CREATE TABLE tbl_a (
    id int PRIMARY KEY,
    some_other_id int,
    value int
) ENGINE=INNODB;
Query OK, 0 rows affected (0.10 sec)

CREATE TABLE tbl_b (
    id int PRIMARY KEY,
    a_id int,
    FOREIGN KEY (a_id) REFERENCES tbl_a (some_other_id)
) ENGINE=INNODB;
ERROR 1005 (HY000): Can't create table 'e.tbl_b' (errno: 150)

но если мы добавим индекс на some_other_id:

CREATE INDEX ix_some_id ON tbl_a (some_other_id);
Query OK, 0 rows affected (0.11 sec)
Records: 0  Duplicates: 0  Warnings: 0

CREATE TABLE tbl_b (
    id int PRIMARY KEY,
    a_id int,
    FOREIGN KEY (a_id) REFERENCES tbl_a (some_other_id)
) ENGINE=INNODB;
Query OK, 0 rows affected (0.06 sec)

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


дважды проверьте, что внешние ключи имеют точно такой же тип, как поле, которое у вас есть в этой таблице. Например, оба должны быть целочисленными (10) или Varchar (8), даже количество символов.


Я понимаю, что это старый пост, но он занимает высокое место в Google, поэтому я добавляю то, что я понял для своей проблемы. Если у вас есть сочетание типов таблиц (например, MyISAM и InnoDB), вы также получите эту ошибку. В этом случае InnoDB является типом таблицы по умолчанию, но одна таблица нуждалась в полнотекстовом поиске, поэтому она была перенесена в MyISAM. В этом случае нельзя создать внешний ключ в таблице InnoDB, который ссылается на таблицу MyISAM.


Если ваш ключ-CHAR / VARCHAR или что-то в этом роде, другой возможной проблемой является другая сортировка. Проверьте, совпадает ли кодировка.


У меня была эта ошибка и я нашел причину ошибки в моем случае. Я все еще отвечаю на этот старый пост, потому что он занимает довольно высокое место в Google.

переменные обоих столбцов, которые я хотел связать, были целыми числами, но один из ints проверил "unsigned". Просто un-проверка, которая исправила мою ошибку.


Я получал ту же ошибку. Я обнаружил решение, что я создал первичный ключ в главной таблице как BIGINT UNSIGNED и объявлял его как внешний ключ во второй таблице как только BIGINT.

когда я объявил свой внешний ключ как BIGINT UNSIGED во второй таблице, все работало нормально, даже не нужно было создавать индексы.

Так было несоответствие данных между первичным ключом и внешним ключом :)


У меня была точно такая же проблема, но решение моей проблемы было совершенно другим. У меня был где-то еще в базе данных внешний ключ с тем же именем. Это вызвало ошибку 1005.

переименование моего внешнего ключа во что-то более конкретное в этой ситуации решило проблему.


  1. убедитесь, что обе таблицы используют один и тот же тип движка.
  2. убедитесь, что индексируемые поля имеют одинаковый тип и длину.

в моем случае ошибка была из-за referencing таблица MyISAM где referring стол InnoDB.

Converted таблица двигатель от MyISAM to InnoDB решает проблему для меня.

ALTER TABLE table_name ENGINE=InnoDB;

У меня еще нет репутации, чтобы проголосовать за предложение Стива, но это решило мою проблему.

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

вы можете изменить тип базы данных, используя: ALTER TABLE T ENGINE = MYISAM;

@see http://dev.mysql.com/doc/refman/5.1/en/storage-engine-setting.html


Это не ваш конкретный случай, но стоит отметить для кого-либо еще, что эта ошибка может возникнуть, если вы попытаетесь ссылаться на некоторые поля в таблице, которые не являются всем первичным ключом этой таблицы. Очевидно, что это запрещено.


Если у кого-то есть эта ошибка с, казалось бы, хорошо сформированными отношениями FK/PK, и вы использовали визуальный инструмент, попробуйте удалить оскорбительные столбцы fk и повторно добавить их в инструмент. Я постоянно получал эту ошибку, пока не перерисовал соединения, которые прояснили проблемы.


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


для меня я пытался сопоставить обычное индексированное поле в дочерней таблице с первичным ключом в родительской таблице, и по умолчанию некоторые интерфейсные интерфейсы MySQL, такие как Sequel Pro, устанавливают первичный ключ как unsigned, поэтому вы должны убедиться, что поле дочерней таблицы тоже без знака (если эти поля не могут содержать отрицательные ints, то убедитесь, что они оба подписаны).


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

помимо проверки того, что два столбца, на которые вы хотите ссылаться в отношениях, имеют одинаковый тип данных, вы также должны убедиться, что столбец в таблице, на которую вы ссылаетесь, является индексом. Если вы используете MySQL Workbench, выберите вкладку "Индексы", рядом с "колоннами" и убедитесь, что столбец, на который ссылается внешний ключ является индексом. Если нет, создайте его, назовите его чем-то значимым и дайте ему тип "индекс".

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

Я надеюсь, что это помогло, некоторые ошибки MySQL сводят с ума, чтобы отслеживать.


обратите внимание на CHARSET и сличить параметры при создании таблицы. С точки зрения внешнего ключа проблемы что-то вроде этого:

CREATE TABLE yourTableName (
....
....
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

в моем случае я не смог создать таблицу со ссылками на внешний ключ. Сначала я получил код ошибки 1005, который почти ничего не говорит. Тогда я добавил COLLATE и, наконец, сообщение об ошибке, жалующееся на кодировку.

Error Code: 1253. COLLATION 'utf8_unicode_ci' is not valid for CHARACTER SET 'latin1'

после этого исправления моей проблемы было решено.


первый вопрос: Могу ли я сделать первичный ключ, который также является внешним ключом?

да. На самом деле для MySQL workbench я привык использовать только первичные ключи для внешних ключей. Действительно сокращает случайные ошибки, полученные, например, err: 150, указанные в вопросе.

# ошибка: Ошибка 1005: не удается создать таблицу ' dbimmobili.condoni' (значение errno: 150)

в этом есть что-то с индексами, или более конкретно, как MySQL workbench интерпретирует и работает с ними. Это действительно запутывается, если вы много меняете в модели (например, внешние ключи, индексы, заказы col) все в той же прямой инженерной операции, особенно, если на другом конце уже есть база данных. Например, я не думаю, что автоматически создаваемые индексы удаляются автоматически после удаления внешнего ключа.

вот что я сделал, чтобы исправить ошибку получения. Отмечать, это кажется громоздким, но по сравнению с количеством времени, которое я потратил, используя другие методы, это не так.

1. Сделайте все внешние ключи первичными ключами в таблице поиска (от 1 до многих).

в моем случае это включало изменение id как pk на username в tbl_users, на username и company в tbl_companies, а также на username и company и contact в tbl_company_contacts. Это приложение для нескольких пользователей, чтобы ввести несколько контактов компании, что позволяет перекрывать и скрытие контактов других пользователей.

2. Удалите все связи диаграмм и все табличные индексы, которые не являются первичными ключами.

это исправляет большинство проблем индекса, которые действительно вызваны багги MySQL workbench.

3. Если вы делаете это от начала до конца, отбросьте схему на сервере, чтобы MySQL workbench не запутался в существующих индексах и не отсутствовал там в модели (проблема вызвана индексом bby и внешним ключом отношения, а не только индекс).

Это уменьшает много решений, которые БД, сервер и MySQL workbench должны сделать много. Эти решения о том, как переслать что-то инженеру, сложны и умны, но несовершенны.

4. Теперь я считаю это обратно в квадрат (как правило, после проектирования слишком быстро без ступенчатого процесса). У меня все еще есть все столы, но на данном этапе они чистые. Теперь ты просто:

во-первых, forward engineer просто чтобы убедиться, что таблицы (без отношений) работают так, как ожидалось.

следуйте цепочке отношений вниз через первичные ключи, начиная с самой верхней таблицы (я-мой случай tbl_users для tbl_companies). После каждого отношения, всегда вперед инженер, чтобы убедиться, что это работает, затем сохраните модель и закройте, а затем перепроектируйте модель, чтобы убедиться, что она принимает. Это позволяет быстро изолируйте проблемы по мере их возникновения, в моем случае остался индекс, используемый старыми удаленными внешними ключами (произошло 2-3 раза).

и tadda, туда, где вы должны быть.