mysql обмеження зовнішнього ключа - неправильно сформована помилка


173

У мене є дві таблиці, table1це батьківська таблиця з колонкою IDі table2з колоною IDFromTable1(не фактичне ім'я) , коли я ставлю на FK , IDFromTable1щоб IDв table1я отримую помилку Foreign key constraint is incorrectly formed error. Я хотів би видалити запис таблиці 2, якщо table1запис буде видалений. Дякуємо за будь-яку допомогу

ALTER TABLE `table2`  
   ADD CONSTRAINT `FK1` 
      FOREIGN KEY (`IDFromTable1`) REFERENCES `table1` (`ID`) 
      ON UPDATE CASCADE 
      ON DELETE CASCADE;

Повідомте мене, чи потрібна будь-яка інша інформація. Я новачок у mysql


4
Який двигун ви використовуєте для своїх столів? Який тип table2.IDFromTable1і table1.ID?
Ромен

5
Також перевірте, чи набори символів для обох таблиць однакові.
Карстен

Дві двигуни обох таблиць є невинні. не знаєте, де знайти набори символів, і обидва - це тип char. Ідентифікатор є первинним ключем у
table1

2
Надайте визначення таблиць для table1 та table2. Як ви отримали цю помилку? Чи використовуєте ви інструмент для створення зовнішнього ключа? Здається, що це не початкова помилка MySQL.
Деварт

@ user516883 - Вам потрібна допомога, щоб отримати визначення таблиць? У HeidiSQL ви можете просто натиснути на вкладку CREATE code .
Альваро Гонсалес

Відповіді:


422

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

Стовпець із зовнішнім ключем був SMALLINT(5) UNSIGNEDі стовпець з посиланням INT(10) UNSIGNED. Після того, як я зробив їх обох такого ж типу, створення іноземних ключів працювало чудово.


58
Або може бути, що посилається стовпець не є первинним ключем
nawfal

9
Якась подібна проблема для мене - таблиця з посиланням ще не існувала. Уопс.
Амальговінус

5
Я повністю пережив те, що зробив Джейк, але я зіткнувся з іншою проблемою FK (різного типу) на HeidiSQL. ФК на варшарах потрібно бути однаковим. Сподіваємось, що допоможе комусь іншому в майбутньому!
cbloss793

10
У моєму випадку це було через різне кодування та зіставлення.
Хатрі

1
@nawfal - Я вважаю, що це не обов'язково повинен бути первинним ключем, але він ОБОВ'ЯЗКОВО має мати індекс. Первинні ключі автоматично індексуються.
Ітаї

48

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

ALTER TABLE parent_table ENGINE=InnoDB;

Дякую тобі велика, я зійшов з розуму від цього. Будь-яка ідея, чому база даних раптом переключить двигун на таблиці?
Роберт Франклін

28

переконайтеся, що стовпці однакові (одного типу), а якщо посилання стовпець - ні primary_key, переконайтеся, що він є INDEXED.


Зі мною навіть траплялося, що помилок не було, але зовнішній ключ не додавали (1 було, а 1 насправді не було), але після додавання простого KEY referencing_column(referencing_column) ДО
ВИКОНАННЯ

2
Ключі, які не індексуються, були моєю проблемою.
Ніл Мастерс

1
У мене виникла ця проблема, і проблема полягає в тому, що у мене був первинний ключ з подвійним стовпцем, і ви не можете використовувати 2-й стовпчик первинного ключа як зовнішній ключ. Тож я просто додав власний індекс для 2-го стовпця первинного ключа, а потім він працював.
Firze

21

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

Не те, щоб ви змішували зіставлення у вашій моделі (чи не так?), Але якщо ви це зробите, будьте впевнені, що ваші основні та зовнішні ключові поля однакового типу зіставлення в phpmyadmin або Heidi SQL або будь-якому іншому, що ви використовуєте.

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


1
Дякую! Виявляється, мій інтернет-хост використовує механізм ISAM, а для локальних розробників - InnoDB. Коли я створив резервну копію таблиці від господаря до місцевого ... буму.
Бен

Останні версії MariaDB, схоже, використовують utf8_mb4 в якості шаблону за замовчуванням (коли не встановлено явно в конфігурації сервера), так це COLLATE utf8mb4_unicode_ciбула моя (несподівана) проблема (на машині розробки).
JonnyJD

13

У мене була така ж проблема, але її вирішили.

Просто переконайтеся, що стовпець "Ідентифікатор" у "table1" має унікальний індекс!

І звичайно, тип, довжина стовпців 'ID' та 'IDFromTable1' у цих двох таблицях повинна бути однаковою. Але ви вже знаєте про це.


Ти зробив мій день.
kevenlolo

1
Радий допомогти! ;)
Ренат Гатін

Невідомі деталі, але у мене був складений ключ із цією помилкою, яку було виправлено додаванням окремих унікальних індексів для стовпців.
Halvor Holsten Strand

Посиланий стовпець повинен бути індексований, він не повинен бути унікальним (хоча це звичайний випадок).
Бармар

10

Просто для завершення.

Ця помилка може бути також випадком, якщо у вас є зовнішній ключ із VARCHAR (..), і набір таблиці згаданої таблиці відрізняється від таблиці, на яку посилається.

наприклад, VARCHAR (50) у таблиці Latin1 відрізняється від VARCHAR (50) у таблиці UTF8.


1
Навіть utf8_unicode_ci та utf8_general_ci викликають помилку
leuchtdiode

10

Тексти помилок mysql не так сильно допомагають, у моєму випадку стовпець мав обмеження "не нульове", тому "видалити встановити нуль" заборонено


7

якщо все нормально, просто додайте ->unsigned();в кінці foregin key.

якщо це не працює, перевірте тип даних обох полів. вони повинні бути однаковими.


5

У мене була однакова проблема, обидва стовпці були INT (11) NOT NULL, але я не зміг створити зовнішній ключ. Мені довелося вимкнути перевірку зовнішніх ключів, щоб її успішно виконати:

SET FOREIGN_KEY_CHECKS=OFF;
ALTER TABLE ... ADD CONSTRAINT ...
SET FOREIGN_KEY_CHECKS=ON;

Сподіваюся, що це комусь допоможе.


4
Насправді це
FOREIGN_KEY_CHECKS

Це допомогло мені пройти далі, але моя проблема була відсутня primmary індексу в колонці
Бумеранг

4

Ще одна вірогідна причина відображення цієї помилки. Порядок, в якому я створював таблиці, був неправильним. Я намагався посилатися на ключ із таблиці, яка ще не була створена.


4

(Остання відповідь) Навіть якщо ім’я поля та тип даних однакові, але зіставлення не однакове, це також призведе до цієї проблеми.

Наприклад

    TBL NAME | ТИП ДАНИХ | КОЛЯЦІЯ        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         utf8_general_ci

Спробуйте змінити його

    TBL NAME | ТИП ДАНИХ | КОЛЯЦІЯ        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         latin1_general_ci

….

Це працювало для мене.


3

Перевірте двигун таблиць, обидві таблиці повинні бути одним і тим же двигуном, що мені так допомогло.


Гарна думка! Я маю справу з базою даних Zen Cart в MySQL, таблиці якої за замовчуванням усі в двигуні MyISAM. Я додав таблицю за допомогою двигуна InnoDB і спробував додати обмеження зовнішнього ключа зі свого столу до ядра Zen Cart. Не вдалось із цією незрозумілою помилкою сформованої помилки. Ви можете бачити двигун для кожної таблиці зSHOW TABLE STATUS LIKE 'table_name';
Neek

2

У мене були ті ж проблеми.

Проблема в тому, що довідковий стовпчик не є первинним ключем.

Зробіть це первинним ключем і проблема вирішена.


Це не повинно бути ПК, це також може бути УНІКАЛЬНО НЕ NULL.
філіпсі

Насправді ... у моєму випадку просто встановити його на індексний тип нормально працював.
hendr1x

2

Хоча інші відповіді дуже корисні, я просто хотів поділитися своїм досвідом.

Я зіткнувся з проблемою, коли я видалив таблицю, на idяку вже згадувались як іноземний ключ в інших таблицях ( з даними ) і намагався відтворити / імпортувати таблицю з деякими додатковими стовпцями.

Запит на відпочинок (згенерований у phpMyAdmin) виглядав так:

CREATE TABLE `the_table` (
  `id` int(11) NOT NULL,            /* No PRIMARY KEY index */  
  `name` varchar(255) NOT NULL,
  `name_fa` varchar(255) NOT NULL,
  `name_pa` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

... /* SOME DATA DUMP OPERATION */

ALTER TABLE `the_table`
  ADD PRIMARY KEY (`id`), /* PRIMARY KEY INDEX */
  ADD UNIQUE KEY `uk_acu_donor_name` (`name`);

Як ви можете помітити, PRIMARY KEYіндекс був встановлений після створення ( та вставки даних) ), що спричинило проблему.

Рішення

Рішення полягало в тому, щоб додати PRIMARY KEYіндекс до запиту визначення таблиці, на idякий посилався як на зовнішній ключ, а також видалити його з ALTER TABLEчастини, де встановлюються індекси:

CREATE TABLE `the_table` (
  `id` int(11) NOT NULL PRIMARY KEY,            /* <<== PRIMARY KEY INDEX ON CREATION */  
  `name` varchar(255) NOT NULL,
  `name_fa` varchar(255) NOT NULL,
  `name_pa` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Це працювало на мене. Я хвилювався, що мені потрібно перевстановити програмне забезпечення;)
Dewlance


1

Спробуйте виконати наступне:

показати створення таблиці батьків

// і перевірте, чи тип для обох таблиць однаковий, як myISAM або innoDB тощо
// Інші аспекти, щоб перевірити це повідомлення про помилку: стовпці, які використовуються як іноземні 
ключі повинні бути проіндексовані, вони повинні бути одного типу 
(якщо тобто один тип smallint (5), а інший типу smallint (6), 
це не буде працювати), і, якщо вони є цілими числами, вони повинні бути непідписані.

// або перевірити наявність шаблонів
показувати такі змінні, як "data_set_database";
показати змінні типу "collation_database";

// відредаговано: спробуйте щось подібне
АЛЬТЕР ТАБЛИЦЯ таблиця2
ДОДАТИ КОНСТРАНТ fk_IdTable2
ІНТЕРНЕТ КЛЮЧ (Таблиця1_Id)
ДОВІДКА Таблиця1 (Таблиця1_Id)
НА ОНОВЛЕННЯ КАСКАДУ 
НА ВІДКРИТИЙ КАСКАД;

9
Спробуйте запустити "SHOW ENGINE INNODB STATUS", щоб отримати детальнішу інформацію про помилку
Sudhir Bastakoti

@SudhirBastakoti - +1! Це зробило це для мене. Деталі корисні. Вдалося усунути проблему швидко.
Пол Карлтон

1

У мене була така сама проблема із Symfony 2.8.

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

Нарешті мені довелося зробити наступне в папці проекту. (Перезапуск сервера не допомогло!)

app/console doctrine:cache:clear-metadata app/console doctrine:cache:clear-query app/console doctrine:cache:clear-result


1

дякую S Doerin:

"Тільки для заповнення. Ця помилка може бути також випадком, якщо у вас є зовнішній ключ з VARCHAR (..), і діаграма згаданої таблиці відрізняється від таблиці, на яку посилається. Наприклад, VARCHAR (50) у таблиці Latin1 відрізняється від VARCHAR (50) у таблиці UTF8. "

я вирішив цю проблему, змінивши тип символів таблиці. у творі є latin1, а правильне - utf8.

додайте наступний рядок. НАСТРОЙКИ ХАРАКТЕРУВАННЯ = utf8;


1

У мене виникли проблеми з використанням таблиці Alter, щоб додати зовнішній ключ між двома таблицями, і те, що мені допомогло, - переконатися, що кожен стовпець, до якого я намагався додати відносини іноземного ключа, був індексований. Для цього в PHP myAdmin: Перейдіть до таблиці та натисніть на вкладку структури. Клацніть на варіант індексу, щоб проіндексувати потрібний стовпець, як показано на знімку екрана:

введіть тут опис зображення

Після того, як я проіндексував обидва стовпчики, на які я намагався посилатися на свої зовнішні ключі, я зміг успішно використовувати таблицю alter і створити зв'язок із зовнішнім ключем. Ви побачите, що стовпці індексуються, як на скріншоті нижче:

введіть тут опис зображення

зауважте, як zip_code відображається в обох таблицях.


1

Вам потрібно перевірити, щоб обидва були однаковими у всіх її властивостях, включно в "Збір"


1

Я використовував HeidiSQL, і щоб вирішити цю проблему, мені довелося створити індекс у посилальній таблиці з усіма стовпцями, на які посилаються.

додавання індексу до таблиці Heidisql


Те саме для мене в mysql: InnoDB вимагає індексів зовнішніх ключів та посилальних ключів, щоб перевірка зовнішніх ключів була швидкою і не вимагала сканування таблиці.
hendr1x

1

Я зіткнувся з тим же питанням саме зараз. У моєму випадку все, що мені потрібно було зробити, це переконатися, що таблиця, на яку я посилаюсь в іноземному ключі, повинна бути створена до поточної таблиці (раніше в коді). Отже, якщо ви посилаєтесь на змінну (x * 5), система повинна знати, що таке x (x повинно бути оголошено в попередніх рядках коду). Це вирішило мою проблему, сподіваюся, це допоможе комусь іншому.


У мене була така ж проблема в MariaDB v10.3.18. Ми раніше використовували MySQL, і він попереджав, що зовнішній ключ вказує на неіснуючу таблицю.
MarthyM

0

У мене була така ж проблема з програмою Lagravel 5.1 для міграції схем з MariaDB 10.1.

Проблема полягала в тому, що я набрав unignedзамість unsigned( sлист відсутній) під час встановлення стовпця.

Після виправлення помилка друку була виправлена ​​для мене.


0

Навіть я зіткнувся з тим же питанням з mysql та liquidibase. Ось у чому полягає така проблема: Таблиця, з якої ви хочете посилатися на стовпець іншої таблиці, відрізняється або за типом даних, або за розміром типу даних.

Error appears in below scenario:
Scenario 1:
Table A has column id, type=bigint
Table B column referenced_id type varchar(this column gets the value from the id column of Table A.)
Liquibase changeset for table B:

    <changeset id="XXXXXXXXXXX-1" author="xyz">
            <column name="referenced_id" **type="varchar"**>
        </column>
            </changeset>
    <changeSet id="XXXXXXXXXXX-2" author="xyz">
                <addForeignKeyConstraint constraintName="FK_table_A"
                    referencedTableName="A" **baseColumnNames="referenced_id**"
                    referencedColumnNames="id" baseTableName="B" />
    </changeSet>

Table A changeSet:

    <changeSet id="YYYYYYYYYY" author="xyz">
     <column **name="id"** **type="bigint"** autoIncrement="${autoIncrement}">
                    <constraints primaryKey="true" nullable="false"/>
                </column>
    </changeSet>

Solution: 
correct the type of table B to bigint because the referenced table has type bigint.

Scenrario 2:
The type might be correct but the size might not.
e.g. :
Table B : referenced column type="varchar 50"
Table A : base column type ="varchar 255"

Solution change the size of referenced column to that of base table's column size.

0

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

 CONSTRAINT `FK_PURCHASE_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `customer` (`id`) ON UPDATE CASCADE ON DELETE CASCADE

до

 CONSTRAINT `FK_PURCHASE_customer_id` FOREIGN KEY (`customer_id`) REFERENCES `CUSTOMER` (`id`) ON UPDATE CASCADE ON DELETE CASCADE

зауважте, що customerзмінено на CUSTOMER.


0

Або ви можете використовувати DBDesigner4, який має графічний інтерфейс для створення вашої бази даних та зв’язування їх за допомогою FK. Клацніть правою кнопкою миші на вашій таблиці та виберіть "Копіювати створення таблиці SQL таблиці", яка створює код.

введіть тут опис зображення


0

Це стара тема, але я щось відкрив. Під час створення робочої версії MySQL він також отримує відносини іншої таблиці. просто залиште стовпи, до яких ви ставитесь. Очистити інші автоматично додані стовпці. Це працює для мене.


0

Моя справа полягала в тому, що я мав друкарську помилку на згаданому стовпчику:

MariaDB [blog]> alter table t_user add FOREIGN KEY ( country_code ) REFERENCES t_country ( coutry_code );
ERROR 1005 (HY000): Can't create table `blog`.`t_user` (errno: 150 "Foreign key constraint is incorrectly formed")

Повідомлення про помилку є доволі виразним, і я спробував усе - перевірку типів стовпців, порівнянь, двигунів тощо.

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

MariaDB [blog]> alter table t_user add FOREIGN KEY ( country_code ) REFERENCES t_country ( country_code );
Query OK, 2 rows affected (0.039 sec)              
Records: 2  Duplicates: 0  Warnings: 0

0

Я зіткнувся з цією проблемою, помилка виникла при введенні первинного ключа в різні типи даних, як-от:

таблиця 1:

 Schema::create('products', function (Blueprint $table) {
            $table->increments('id');
            $table->string('product_name');
        });

таблиця 2:

Schema::create('brands', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('brand_name');
        });

тип даних для ідентифікатора другої таблиці повинен бути кроком


0

Проблема вирішується дуже просто

наприклад: у вас є дві таблиці з іменами користувачів і публікацій, і ви хочете створити зовнішній ключ у таблиці повідомлень, і ви використовуєте phpMyAdmin

1) у таблицю публікацій додайте новий стовпець ( ім'я : use_id | тип : як ідентифікатор в таблиці користувачів | Довжина : як ідентифікатор в таблиці користувачів | За замовчуванням : NULL | Атрибути : без підпису | | індекс: INDEX)

2) на вкладці Структура перейдіть до перегляду відносин ( Назва обмеження : автоматично встановлено phpmyAdmin | ім'я стовпця : виберіть user_id | таблиця : користувач | ключ : id, ...)

Це було просто вирішено

javad mosavi iran / urmia

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.