2009-09-21 2 views
93

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

Вот SQL для всех 3-х таблиц:

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; 

Любая помощь будет принята с благодарностью.

+1

Не могли бы вы создавать вывод сообщения об ошибке и скажите нам, какую команду (из трех) вызывает ошибку? – dave

+4

Что происходит с обратными тиками вокруг 'auto_increment'? Это неверно. Auto_increment - это ключевое слово, а не идентификатор. –

ответ

10

Каково текущее состояние вашей базы данных при запуске этого скрипта? Он полностью пуст? Ваш SQL работает отлично для меня при создании базы данных с нуля, но errno 150 обычно имеет дело с удалением & воссоздающих таблиц, которые являются частью внешнего ключа. Я получаю ощущение, что вы не работаете со 100% новой и новой базой данных.

Если вы ошибаетесь, когда «источник» - ваш файл SQL, вы можете запустить команду «SHOW ENGINE INNODB STATUS» из приглашения MySQL сразу после команды «source», чтобы увидеть более подробную ошибку Информация.

Вы можете проверить ручной ввод тоже:

Если вы заново создать таблицу, которая была сброшена, она должна иметь определение, которое соответствует к внешнему ключу, ссылающихся его. Он должен иметь правильные имена и типы столбцов, и он должен иметь индексы на ссылочных ключах, как указано ранее. Если они не выполняются, MySQL возвращает номер ошибки 1005 и ссылается на ошибку 150 в сообщении об ошибке. Если MySQL сообщает номер ошибки 1005 из инструкции CREATE TABLE, а сообщение об ошибке относится к ошибке 150, создание таблицы завершилось неудачно, потому что ограничение внешнего ключа было неправильно сформировано.

- MySQL 5.1 reference manual.

25

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

Часто свойство «без знака» в столбце «ID» выведет вас на улицу.

ALTER TABLE `dbname`.`tablename` CHANGE `fieldname` `fieldname` int(10) UNSIGNED NULL; 
+1

спасибо, что это было правдой. –

+0

По моему опыту, стоит использовать SHOW CREATE TABLE MySQL в вашей основной таблице, чтобы точно проверить, какие флаги установлены против вашего основного столбца индекса, а затем скопировать их в столбец внешнего ключа. Там могут быть такие вещи, как «неподписанные», которые не очевидны. – Ambulare

221

У меня была такая же проблема с ALTER TABLE ADD FOREIGN KEY.

Через час, я обнаружил, что эти условия должны быть выполнены, чтобы не получить ошибку 150:

  1. В таблице Родитель должен существовать, прежде чем определить внешний ключ для ссылки на нее. Вы должны определить таблицы в правильном порядке: сначала родительскую таблицу, затем таблицу «Дети». Если обе таблицы ссылаются друг на друга, вы должны создать одну таблицу без ограничений FK, затем создать вторую таблицу, а затем добавить ограничение FK к первой таблице с помощью ALTER TABLE.

  2. Две таблицы должны поддерживать ограничения внешнего ключа, то есть ENGINE=InnoDB. Другие системы хранения молча игнорируют определения внешних ключей, поэтому они не возвращают никаких ошибок или предупреждений, но ограничение FK не сохраняется.

  3. Указанные столбцы в родительской таблице должны быть самыми левыми столбцами ключа. Лучше, если ключ в Родитель PRIMARY KEY или UNIQUE KEY.

  4. Определение FK должно ссылаться на столбцы (столбцы) PK в том же порядке, что и определение PK. Например, если FK REFERENCES Parent(a,b,c), то PK родителя не должен быть определен в столбцах в порядке (a,c,b).

  5. Столбец PK в родительской таблице должен быть того же типа данных, что и столбец FK в таблице Child. Например, если столбец PK в родительской таблице равен UNSIGNED, обязательно укажите UNSIGNED для соответствующего столбца в поле «Детская таблица».

    Исключение: длина строк может быть разной. Например, VARCHAR(10) может ссылаться на VARCHAR(20) или наоборот.

  6. Любые столбцы (столбцы) FK строкового типа должны иметь одинаковый набор символов и сопоставление в качестве соответствующих столбцов (столбцов) PK.

  7. Если в таблице «Дети» есть данные, каждое значение в столбце (столбцах) FK должно соответствовать значению в столбце (столбцах) столбца родительской таблицы. Проверьте это с помощью запроса, например:

    SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK 
    WHERE Parent.PK IS NULL; 
    

    Это должно возвращать нулевые (0) непревзойденные значения. Очевидно, что этот запрос является общим примером; вы должны заменить имена таблиц и имена столбцов.

  8. Ни родительский стол, ни таблица для детей не могут быть столбиком TEMPORARY.

  9. Ни родительский стол, ни таблица для детей могут быть столом PARTITIONED.

  10. Если вы заявляете FK с опцией ON DELETE SET NULL, то столбец FK должен иметь значение NULL.

Надеюсь, это поможет.

+3

Это действительно помогает, спасибо. –

+4

еще одна вещь стоит добавить: если PK родительской таблицы больше, чем одно поле, порядок полей в FK должен быть таким же, как и порядок в PK – Kip

+1

Это определенно помогло мне найти реальную проблему. Имя моей таблицы было всего прописным, а ссылочная часть FK ссылалась на таблицу в нижнем регистре.(Не упоминается напрямую, но я систематически проверял, что информация PK и FK была одинаковой. – purgatory101

3

Для других, кто находит эту запись SO через Google: убедитесь, что вы не пытаетесь выполнить действие SET NULL на столбце внешнего ключа, который должен быть указан как «NOT NULL». Это вызвало сильное разочарование, пока я не вспомнил о том, что нужно сделать CHECK ENGINE INNODB STATUS.

5

Для людей, просматривающие эту тему с той же проблемой:

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

MySQL Foreign Key Errors and Errno 150

0

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

1

Это обычно происходит, когда вы пытаетесь загрузить исходный файл в существующую базу данных. Сначала отбросьте все таблицы (или сам БД). И затем исходный файл с SET foreign_key_checks = 0; в начале и SET foreign_key_checks = 1; в конце.

0

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

57

Сообщение об ошибке «errno 150» от MySQL «means that a foreign key constraint was not correctly formed». Как вы, вероятно, уже знаете, читаете ли вы эту страницу, общее сообщение об ошибке «errno: 150» действительно бесполезно. Однако:

Вы можете получить сообщение об ошибке в фактической, запустив SHOW ENGINE INNODB STATUS;, а затем ищет LATEST FOREIGN KEY ERROR на выходе.

Например, это попытка создать ограничение внешнего ключа:

CREATE TABLE t1 
(id INTEGER); 

CREATE TABLE t2 
(t1_id INTEGER, 
CONSTRAINT FOREIGN KEY (t1_id) REFERENCES t1 (id)); 

завершается с ошибкой Can't create table 'test.t2' (errno: 150). Это не говорит никому ничего полезного, кроме того, что это проблема внешнего ключа. Но запустить SHOW ENGINE INNODB STATUS; и он будет говорить:

------------------------ 
LATEST FOREIGN KEY ERROR 
------------------------ 
130811 23:36:38 Error in foreign key constraint of table test/t2: 
FOREIGN KEY (t1_id) REFERENCES t1 (id)): 
Cannot find an index in the referenced table where the 
referenced columns appear as the first columns, or column types 
in the table and the referenced table do not match for constraint. 

Это говорит о том, что проблема в том, что не может найти индекс. SHOW INDEX FROM t1 показывает, что индексов нет для таблицы t1. Исправьте это, скажем, определив первичный ключ на t1, и ограничение внешнего ключа будет создано успешно.

+4

'SHOW ENGINE INNODB STATUS' помог мне сразу определить проблему, которую я пытался диагностировать почти час. Благодарю. – jatrim

2

Полезный совет, используйте SHOW WARNINGS; после попытки вашего CREATE запроса и вы получите сообщение об ошибке, а также более подробного предупреждение:

---------------------------------------------------------------------------------------------------------+ 
| Level | Code | Message                                                         | 
+---------+------+--------------------------------------------------------------------------       --------------------------------------------------------------------------------------------       ---------------+ 
| Warning | 150 | Create table 'fakeDatabase/exampleTable' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns. 
| 
| Error | 1005 | Can't create table 'exampleTable' (errno:150)                                           | 
+---------+------+--------------------------------------------------------------------------       --------------------------------------------------------------------------------------------       ---------------+ 

Так что в этом случае время, чтобы заново создать свой стол!

1

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

Для этого определения таблицы

CREATE TABLE user (
    userId int PRIMARY KEY AUTO_INCREMENT, 
    username varchar(30) NOT NULL 
) ENGINE=InnoDB; 

Это определение таблицы работает

CREATE TABLE product (
    id int PRIMARY KEY AUTO_INCREMENT, 
    userId int, 
    FOREIGN KEY fkProductUser1(userId) REFERENCES **u**ser(userId) 
) ENGINE=InnoDB; 

в то время как этот терпит неудачу

CREATE TABLE product (
    id int PRIMARY KEY AUTO_INCREMENT, 
    userId int, 
    FOREIGN KEY fkProductUser1(userId) REFERENCES User(userId) 
) ENGINE=InnoDB; 

Тот факт, что он работал на Windows, и не на Unix взял меня пару часов, чтобы разобраться. Надеюсь, что это помогает кому-то другому.

0

В моем случае это было связано с тем, что поле, являющееся полем внешнего ключа, имеет слишком длинное имя, т.е. foreign key (some_other_table_with_long_name_id). Попробуйте коротко. В этом случае сообщение об ошибке немного вводит в заблуждение.

Кроме того, как @Jon упоминалось ранее - определения полей должны быть одинаковыми (следите за подтипом unsigned).

3

Определенно это не так, но я нашел эту ошибку довольно распространенной и неочевидной. Целью FOREIGN KEY может быть не PRIMARY KEY. Ответ, который мне пригодится, - это:

ИНОСТРАННЫЙ КЛЮЧ всегда следует указывать на истинное поле PRIMARY KEY другой таблицы.

CREATE TABLE users(
    id INT AUTO_INCREMENT PRIMARY KEY, 
    username VARCHAR(40)); 

CREATE TABLE userroles(
    id INT AUTO_INCREMENT PRIMARY KEY, 
    user_id INT NOT NULL, 
    FOREIGN KEY(user_id) REFERENCES users(id)); 
+0

Это была моя проблема. Ужасная отчетность об ошибках, MySQL ... –

0

Когда ограничение foraign ключ на основе varchar типа, то в дополнение к list provided by marv-elцелевой столбец должен иметь уникальное ограничение.

3

Как указано @andrewdotn, лучший способ - увидеть подробную ошибку (SHOW ENGINE INNODB STATUS;) вместо кода ошибки.

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

1

MySQL Workbench 6.3 для Mac OS.

Проблема: errno 150 на столе X при попытке сделать Forward Engineering на диаграмме DB, 20 из 21 удалось, 1 не удалось. Если FKs на таблице X были удалены, ошибка переместилась в другую таблицу, которая не была провалена раньше.

Изменил все движки таблиц на myISAM, и он работал отлично.

enter image description here

2

Пожалуйста, убедитесь сначала, что

  1. вы используете InnoDB таблицы.
  2. Поле FOREIGN KEY имеет тип и длину (!) В качестве исходного поля.

У меня была такая же проблема, и я исправил ее. У меня было unsigned INT для одного поля и целое число для другого поля.

0

(Боковые ноты слишком большие для комментария)

Там нет необходимости для AUTO_INCREMENT идентификатора в таблице отображения; избавиться от этого.

Измените PRIMARY KEY на (role_id, role_group_id) (в любом порядке). Это сделает доступ быстрее.

Поскольку вы, вероятно, хотите отобразить оба направления, также добавьте INDEX с этими двумя столбцами в обратном порядке. (Там нет необходимости, чтобы сделать его UNIQUE.)

Другие советы: http://mysql.rjweb.org/doc.php/index_cookbook_mysql#speeding_up_wp_postmeta