Я пытаюсь создать таблицу в MySQL с двумя внешними ключами, которые ссылаются на первичные ключи в двух других таблицах, но я получаю ошибку errno: 150, и таблица не создается.
Вот SQL для всех трех таблиц:
CREATE TABLE role_groups (
`role_group_id` int(11) NOT NULL `AUTO_INCREMENT`,
`name` varchar(20),
`description` varchar(200),
PRIMARY KEY (`role_group_id`)
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `roles` (
`role_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50),
`description` varchar(200),
PRIMARY KEY (`role_id`)
) ENGINE=InnoDB;
create table role_map (
`role_map_id` int not null `auto_increment`,
`role_id` int not null,
`role_group_id` int not null,
primary key(`role_map_id`),
foreign key(`role_id`) references roles(`role_id`),
foreign key(`role_group_id`) references role_groups(`role_group_id`)
) engine=InnoDB;
Любая помощь будет принята с благодарностью.
mysql
foreign-keys
mysql-error-150
Билл Карвин
источник
источник
auto_increment
? Это неверно. Auto_increment - это ключевое слово, а не идентификатор.Ответы:
У меня была такая же проблема с
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
соответствующий столбец в поле дочерней таблицы.Исключение: длина строк может быть разной. Например,
VARCHAR(10)
можно ссылатьсяVARCHAR(20)
или наоборот.Любые столбцы FK строкового типа должны иметь тот же набор символов и сопоставление, что и соответствующие столбцы PK.
Если в дочерней таблице уже есть данные, каждое значение в столбце (ах) FK должно соответствовать значению в столбце (ах) родительской таблицы. Проверьте это с помощью такого запроса:
Это должно вернуть ноль (0) несогласованных значений. Очевидно, что этот запрос является общим примером; вы должны заменить имена таблиц и столбцов.
Ни родительская таблица, ни дочерняя таблица не могут быть
TEMPORARY
таблицей.Ни родительская таблица, ни дочерняя таблица не могут быть
PARTITIONED
таблицей.Если вы объявляете FK с
ON DELETE SET NULL
опцией, то столбцы FK должны допускать значение NULL.Если вы объявляете имя ограничения для внешнего ключа, имя ограничения должно быть уникальным во всей схеме, а не только в таблице, в которой определено ограничение. Две таблицы могут не иметь собственного ограничения с одинаковым именем.
Если в других таблицах есть какие-либо другие FK, указывающие на то же поле, для которого вы пытаетесь создать новый FK, и они имеют неправильный формат (т. Е. Другое сопоставление), их необходимо сначала согласовать. Это может быть результатом прошлых изменений, которые
SET FOREIGN_KEY_CHECKS = 0;
использовались с несовместимыми отношениями, определенными по ошибке. См. Ответ @andrewdotn ниже, чтобы узнать, как определить эти проблемные FK.Надеюсь это поможет.
источник
int(11) unsigned NOT NULL
противint(11) NOT NULL
.ON DELETE
правило ОГРАНИЧЕНИЯ -SET NULL
убедитесь, что внешний ключ действительно может иметь значение NULL! Я потратил 30 минут на чтение этого ответа снова и снова, проверяя, соответствуют ли мои таблицы условиям, но все еще получаю ошибку 150. Затем я заметил, что мое поле FK было НЕ NULL, что означает, что правило было невозможно применить.Общее сообщение MySQL «errno 150» « означает, что ограничение внешнего ключа было неправильно сформировано ». Как вы, вероятно, уже знаете, если читаете эту страницу, типичное сообщение об ошибке «errno: 150» действительно бесполезно. Тем не мение:
Вы можете получить фактическое сообщение об ошибке, запустив
SHOW ENGINE INNODB STATUS;
и выполнив поискLATEST FOREIGN KEY ERROR
в выводе.Например, эта попытка создать ограничение внешнего ключа:
выходит из строя с ошибкой
Can't create table 'test.t2' (errno: 150)
. Это никому не говорит ничего полезного, кроме того, что это проблема внешнего ключа. Но беги,SHOW ENGINE INNODB STATUS;
и он скажет:Он говорит, что проблема в том, что он не может найти индекс.
SHOW INDEX FROM t1
показывает, что для таблицы вообще нет индексовt1
. Исправьте это, скажем, определив первичный ключt1
, и ограничение внешнего ключа будет успешно создано.источник
SHOW ENGINE INNODB STATUS
помог мне сразу определить проблему, которую я пытался диагностировать почти час. Спасибо.SET FOREIGN_KEY_CHECKS = 0;
во время импорта / изменения, которое было искажено в то или иное время. Большая помощь, спасибо.Убедитесь, что свойства двух полей, которые вы пытаетесь связать с ограничением, в точности совпадают.
Часто вас уловит свойство «без знака» в столбце идентификатора.
источник
Каково текущее состояние вашей базы данных при запуске этого сценария? Он совсем пустой? Ваш SQL отлично работает для меня при создании базы данных с нуля, но ошибка 150 обычно связана с удалением и воссозданием таблиц, которые являются частью внешнего ключа. У меня такое чувство, что вы работаете не со 100% свежей и новой базой данных.
Если вы ошибаетесь, когда "исходный" вводит ваш файл SQL, вы должны иметь возможность запустить команду "SHOW ENGINE INNODB STATUS" из командной строки MySQL сразу после команды "source", чтобы увидеть более подробную информацию об ошибке.
Вы также можете проверить ручной ввод:
источник
Для людей, которые просматривают эту ветку с той же проблемой:
Есть много причин для появления подобных ошибок. Для получения достаточно полного списка причин и решений ошибок внешнего ключа в MySQL (включая обсуждаемые здесь) перейдите по этой ссылке:
Ошибки внешнего ключа MySQL и Errno 150
источник
Для других, кто нашел эту запись SO через Google: убедитесь, что вы не пытаетесь выполнить действие SET NULL для столбца (должен быть) внешнего ключа, определенного как «NOT NULL». Это вызывало большое разочарование, пока я не вспомнил, что нужно выполнить CHECK ENGINE INNODB STATUS.
источник
Определенно это не так, но я считаю эту ошибку довольно частой и неочевидной. Мишенью
FOREIGN KEY
не могло бытьPRIMARY KEY
. Ответ, который мне пригодился:FOREIGN KEY всегда должен указываться на поле PRIMARY KEY true другой таблицы.
источник
Как указано @andrewdotn, лучший способ - увидеть подробную ошибку (
SHOW ENGINE INNODB STATUS;
), а не просто код ошибки.Одна из причин может заключаться в том, что индекс с таким же именем уже существует, может быть в другой таблице. На практике я рекомендую ставить имя таблицы перед именем индекса, чтобы избежать таких конфликтов. например, вместо
idx_userId
использованияidx_userActionMapping_userId
.источник
Пожалуйста, сначала убедитесь, что
У меня была такая же проблема, и я ее исправил. У меня был беззнаковый INT для одного поля и просто целое число для другого поля.
источник
Полезный совет, используйте
SHOW WARNINGS;
после попыткиCREATE
запроса, и вы получите сообщение об ошибке, а также более подробное предупреждение:Итак, в этом случае пришло время воссоздать мою таблицу!
источник
Обычно это происходит, когда вы пытаетесь добавить исходный файл в существующую базу данных. Сначала удалите все таблицы (или саму БД). И затем исходный файл с
SET foreign_key_checks = 0;
в начале иSET foreign_key_checks = 1;
в конце.источник
Я нашел еще одну причину, по которой это не удается ... имена таблиц с учетом регистра.
Для этого определения таблицы
Это определение таблицы работает
тогда как этот терпит неудачу
На то, что он работал в Windows и не работал в Unix, у меня ушло несколько часов. Надеюсь, это поможет кому-то другому.
источник
MySQL Workbench 6.3 для Mac OS.
Проблема: ошибка 150 в таблице X при попытке выполнить форвардное проектирование на диаграмме БД, 20 из 21 успешных, 1 не удалось. Если FK в таблице X были удалены, ошибка перемещалась в другую таблицу, в которой раньше не было ошибок.
Изменил весь движок таблиц на myISAM, и он работал нормально.
источник
Также стоит убедиться, что вы случайно не работаете с неправильной базой данных. Эта ошибка возникает, если сторонняя таблица не существует. Почему MySQL должен быть таким загадочным?
источник
Убедитесь, что внешние ключи не указаны как уникальные в родительском элементе. У меня была такая же проблема, и я решил ее, обозначив ее как не уникальную.
источник
В моем случае это было из-за того, что поле, которое было полем внешнего ключа, имело слишком длинное имя, т.е.
foreign key (some_other_table_with_long_name_id)
. Попробуйте что-нибудь короче. В этом случае сообщение об ошибке может ввести в заблуждение.Кроме того, как упоминал ранее @Jon - определения полей должны быть одинаковыми (обратите внимание на
unsigned
подтип).источник
(Боковые заметки слишком велики для комментария)
Нет необходимости в
AUTO_INCREMENT
идентификаторе в таблице сопоставления; избавиться от этого.Изменение
PRIMARY KEY
к(role_id, role_group_id)
(в любом порядке). Это ускорит доступ.Поскольку вы, вероятно, захотите отобразить оба направления, также добавьте
INDEX
эти два столбца в обратном порядке. (Нет необходимости делать этоUNIQUE
.)Дополнительные советы: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta
источник
Когда ограничение внешнего ключа на основе
varchar
типа, то в дополнение к списку , предоставленномуmarv-el
в целевой столбец должен иметь уникальное ограничение.источник
перед созданием таблицы выполнить строку ниже: SET FOREIGN_KEY_CHECKS = 0;
Параметр FOREIGN_KEY_CHECKS указывает, следует ли проверять ограничения внешнего ключа для таблиц InnoDB.
- Укажите, чтобы проверить ограничения внешнего ключа (это значение по умолчанию)
- Не проверять ограничения внешнего ключа
УСТАНОВИТЬ FOREIGN_KEY_CHECKS = 0;
Когда использовать: временное отключение реляционных ограничений (установите FOREIGN_KEY_CHECKS на 0) полезно, когда вам нужно воссоздать таблицы и загрузить данные в любом порядке родитель-потомок.
источник
Я столкнулся с той же проблемой, но проверяю, что у меня нет родительской таблицы. Поэтому я просто редактирую родительскую миграцию перед дочерней миграцией. Просто сделай это.
источник