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


85

У мене виникають деякі проблеми зі створенням зовнішнього ключа до існуючої таблиці в базі даних 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 charset, але ви отримаєте мою підтримку за те, щоб я задумався.
user2910265

Відповіді:


153

Просто кинувши це в поєднання можливих причин, я зіткнувся з цим, коли стовпець таблиці посилань мав той самий "тип", але не мав однакового підпису.

У моєму випадку стовпець таблиці посилань був TINYINT UNSIGNED, а стовпець таблиці посилань TINYINT SIGNED. Вирівнювання обох стовпців вирішило проблему.


1
Рішення, запропоноване @ austen-hoogen, вирішило мою проблему. Але через низькі показники репутації я не можу проголосувати і прокоментувати його рішення. У моєму випадку первинним ключем було ціле число, автоматичне збільшення та без знака. Але зовнішній ключ (стовпець таблиці посилань) був підписаного типу. Я змінив його на unsigned та зміг створити відношення успішно.
Бал Сінгх,

Так, пройшов те саме питання. Моїм первинним ключем був BIGINT (20), а моїм посиланим ключем в іншій таблиці - INT (10) без підпису. ми потребуємо, щоб переконатися, що всі вони збігаються. тобто BIGINT (20), а в таблиці, на яку посилаються, також має бути BIGINT (20)
Манджунатх Редді

Дякую! Це рішення також вирішило мою проблему! Я мав intу таблиці, де я планував встановити зовнішній ключ та bigint у другій таблиці.
Aleksej_Shherbak

36

Ця помилка також може статися, якщо таблиця посилань і поточна таблиця не мають однакового набору символів.


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

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 Саме
Герма Вінсмок


6

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

  • Спочатку я запустив запит у таблиці, на яку посилається, щоб отримати тип сортування
show table STATUS like '<table_name_here>';
  • Потім я скопіював тип сортування та чітко вказав тип сортування worker_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

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

Але я виявив, що невизначення його як унікального не створює проблем у кожному випадку. Однак мені не вдалося з'ясувати сценарії розвитку подій. Можливо, щось пов’язане з визнанням, яке можна обнулити.


Чи читали ви вступ до ФК чи посібник? ФК посилається на УНІКАЛЬНИЙ; PK означає УНІКАЛЬНИЙ НЕ НУЛЬНИЙ.
Філіпсія

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.