MySQL не может создать ограничение внешнего ключа


87

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

У меня есть таблица exp:

+-------------+------------------+------+-----+---------+-------+
| Field       | Type             | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+-------+
| EID         | varchar(45)      | NO   | PRI | NULL    |       |
| Comment     | text             | YES  |     | NULL    |       |
| Initials    | varchar(255)     | NO   |     | NULL    |       |
| ExpDate     | date             | NO   |     | NULL    |       |
| InsertDate  | date             | NO   |     | NULL    |       |
| inserted_by | int(11) unsigned | YES  | MUL | NULL    |       |
+-------------+------------------+------+-----+---------+-------+

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

CREATE TABLE sample_df (
df_id mediumint(5) unsigned AUTO_INCREMENT primary key,
sample_type mediumint(5) unsigned NOT NULL,
df_10 BOOLEAN NOT NULL,
df_100 BOOLEAN NOT NULL,
df_1000 BOOLEAN NOT NULL,
df_above_1000 BOOLEAN NOT NULL,
target INT(11) unsigned NOT NULL,
assay MEDIUMINT(5) unsigned zerofill NOT NULL,
insert_date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
inserted_by INT(11) unsigned NOT NULL,
initials varchar(255),
experiment VARCHAR(45),
CONSTRAINT FOREIGN KEY (inserted_by) REFERENCES user (iduser),
CONSTRAINT FOREIGN KEY (target) REFERENCES protein (PID),
CONSTRAINT FOREIGN KEY (sample_type) REFERENCES sample_type (ID),
CONSTRAINT FOREIGN KEY (assay) REFERENCES assays (AID),
CONSTRAINT FOREIGN KEY (experiment) REFERENCES exp (EID)
);

Но я получаю ошибку:

ERROR 1215 (HY000): Cannot add foreign key constraint

Чтобы получить дополнительную информацию, я сделал:

SHOW ENGINE INNODB STATUS\G

Из чего я получил:

FOREIGN KEY (experiment) REFERENCES exp (EID)
):
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.

Мне кажется, что типы столбцов совпадают, так как они оба типа varchar (45). (Я также пытался установить значение experimentстолбца не равным нулю, но это не помогло) Так что, я думаю, проблема в этом Cannot find an index in the referenced table where the referenced columns appear as the first columns. Но я не совсем уверен, что это значит и как это проверить / исправить. У кого-нибудь есть предложения? А что имеется ввиду first columns?


11
Ни в одном ответе или вопросе я не смог обнаружить, что эта ошибка может возникнуть из-за разницы в наборе символов. Спасибо .. Ура !!!
proprius

3
Кроме того, дважды проверьте параметры сортировки столбцов. Ваша таблица может быть utf8mb4, но столбец может иметь другое сопоставление!
Watson

@Watson charset в моем случае, но вы получаете мой голос за то, что заставили меня задуматься.
user2910265

Ответы:


155

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

В моем случае столбец таблицы, на который ссылаются, был TINYINT UNSIGNED, а столбец таблицы ссылок был TINYINT SIGNED. Выравнивание обоих столбцов решило проблему.


2
Решение, предложенное @ austen-hoogen, разрешило мою проблему. Но из-за низкой репутации я не могу голосовать и комментировать его решение. В моем случае первичный ключ был целочисленным, с автоматическим приращением и без знака. Но внешний ключ (столбец ссылочной таблицы) был подписанным. Я изменил его на беззнаковый и смог успешно создать отношение.
Бал Сингх

Да, прошел через ту же проблему. Мой первичный ключ был BIGINT (20), а мой ссылочный ключ в другой таблице был INT (10) без знака. мы должны убедиться, что все они совпадают. т.е. BIGINT (20), а в указанной таблице также должно быть BIGINT (20)
Manjunath Reddy

Спасибо! Это решение тоже решило мою проблему! У меня была intтаблица, в которой я планировал установить внешний ключ и bigint во второй таблице.
Aleksej_Shherbak

38

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


3
После установки набора символов, как latinв указанной таблице, я снова начал дышать через 3 часа.
Абхишек Камаль

Спасибо. Это нетривиальный вопрос
Ventoh

24

Согласно http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html

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

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

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

Причина нашей ошибки - нарушение следующего правила:

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


20

Как упоминалось в @Anton, это может быть из-за другого типа данных. В моем случае у меня был первичный ключ BIGINT (20), и я пытался установить передний ключ с INT (10)


2
Спасибо! Аналогичная проблема, когда я использовал INT (11) с INT (11), но один был первичным ключом и, следовательно, без подписи, а другой был подписан!
Майкл Скотт Катберт

@MichaelScottCuthbert Same
Джерма Винсмок

7

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

  • Сначала я выполнил запрос в указанной таблице, чтобы получить ее тип сопоставления
show table STATUS like '<table_name_here>';
  • Затем я скопировал тип сопоставления и явно указал тип сопоставления employee_id в запросе на создание. В моем случае это был utf8_general_ci
CREATE TABLE dbo.sample_db
(
  id INT PRIMARY KEY AUTO_INCREMENT,
  event_id INT SIGNED NOT NULL,
  employee_id varchar(45) COLLATE utf8_general_ci NOT NULL,
  event_date_time DATETIME,
  CONSTRAINT sample_db_event_event_id_fk FOREIGN KEY (event_id) REFERENCES event (event_id),
  CONSTRAINT sample_db_employee_employee_id_fk FOREIGN KEY (employee_id) REFERENCES employee (employee_id)
);


2

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

У меня была настройка первичного ключа, где порядок столбцов фактически совпадает, но проблема заключалась в том, что первичный ключ имел дополнительный столбец в нем, который не является частью внешнего ключа ссылочной таблицы

например) таблица 2, столбец (a, b, c) -> таблица 1, столбец (a, b, d, c) - ЭТА НЕИСПРАВНОСТЬ

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

например) таблица 2, столбец (a, b, c) -> таблица 1, столбец (a, b, c, d) - ЭТО УСПЕХИ


2

В некоторых случаях мне приходилось делать указанное поле уникальным помимо определения его как первичного ключа.

Но я обнаружил, что не определение его как уникального не во всех случаях создает проблему. Однако я не смог разобраться в сценариях. Вероятно, что-то связано с определением, допускающим значение NULL.


Вы читали введение в FKs или руководство? FK ссылается на УНИКАЛЬНЫЙ; PK означает UNIQUE NOT NULL.
Филипси

2

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

Это вызвало большой кошмар в моем приложении Rails, поскольку миграция не удалась, но поля были фактически созданы в БД, поэтому они отображались в БД, но не в схеме приложения Rails.


1

Ссылка на один и тот же столбец более одного раза в одном и том же ограничении также вызывает эту Cannot find an index in the referenced tableошибку, но ее может быть трудно обнаружить в больших таблицах. Разделите ограничения, и все будет работать, как ожидалось.


1

У меня тоже была эта ошибка. Ни один из ответов не относился ко мне. В моем случае мой графический интерфейс автоматически создает таблицу с основным уникальным идентификатором как «неназначенный». Это не удается, когда я пытаюсь создать внешний ключ, и выдает ту же ошибку. Мой первичный ключ должен быть назначен.

Если вы пишете сам SQL таким образом, у id int unique auto_incrementвас нет этой проблемы, но по какой-то причине мой графический интерфейс делает это вместо этого id int unassigned unique auto_increment.

Надеюсь, это поможет кому-то еще в будущем.


1

Для меня это была просто кодировка и сопоставление БД. Перешел на utf8_unicode_ci и работает


1
Не могли бы вы включить пример того, как проверить текущую кодировку / сопоставление?
thelr
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.