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
Также убедитесь, что наборы символов для обеих таблиц одинаковы.
Карстен

Обе таблицы движков находятся в innoDB. не уверен, где найти наборы символов, и оба типа char. Идентификатор является первичным ключом в
таблице 1

2
Пожалуйста, предоставьте определения таблиц для table1 и table2. Как вы получили эту ошибку? Используете ли вы инструмент для создания внешнего ключа? Кажется, что это не ошибка MySQL.
Деварт

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

Ответы:


422

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

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


58
Или может быть, что указанный столбец не является первичным ключом
nawfal

9
Вроде бы похожая проблема для меня - ссылочная таблица еще не существовала. Упс.
Амальговинус

5
Я полностью испытал то, что сделал Джейк, но я столкнулся с другой проблемой FK (другого типа) на HeidiSQL. FK на varchars должен быть одинаковым сопоставлением. Надеюсь, что это поможет кому-то еще в будущем!
cbloss793

10
В моем случае это было из-за разной кодировки и сортировки.
Хатри

1
@nawfal - я считаю, что это не обязательно должен быть первичный ключ, но он ДОЛЖЕН иметь индекс. Первичные ключи автоматически индексируются.
Итай

48

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

ALTER TABLE parent_table ENGINE=InnoDB;

Большое спасибо, я схожу с ума от этого. Любая идея, почему база данных внезапно переключит двигатель для таблиц?
Роберт Франклин

28

убедитесь, что столбцы идентичны (одного типа), а если ссылочный столбец - нет primary_key, убедитесь, что это так INDEXED.


Со мной даже случилось, что ошибки не было, но внешний ключ не был добавлен (1 был, а 1 на самом деле не был), но после добавления простого KEY referencing_column(referencing_column) ДО определения обоих внешних ключей они оба были добавлены успешно :)
jave.web

2
Ключи, не индексируемые, были моей проблемой.
Нил Мастерс

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

21

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

Не то, чтобы вы смешивали параметры сортировки в вашей модели (не так ли?), Но если вы это сделаете, убедитесь, что поля первичного и внешнего ключей имеют одинаковый тип сопоставления в phpmyadmin или Heidi SQL или в любом другом используемом вами формате.

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


1
Спасибо! Оказывается, мой онлайн-хост использует движок ISAM, а для локального разработчика я использую InnoDB. Когда я зарезервировал стол с хоста на местный ... бум.
Бен

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

13

У меня была такая же проблема, но я решил ее.

Просто убедитесь, что столбец 'ID' в 'table1' имеет уникальный индекс!

И, конечно, тип, длина столбцов 'ID' и 'IDFromTable1' в этих двух таблицах должны быть одинаковыми. Но вы уже знаете об этом.


Вы сделали мой день.
Кевенлоло

1
Рад помочь! ;)
Ренат Гатин

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

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

10

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

Эта ошибка также может иметь место, если у вас есть внешний ключ с VARCHAR (..) и кодировка таблицы, на которую ссылаются, отличается от таблицы, ссылающейся на нее.

Например, VARCHAR (50) в таблице Latin1 отличается от VARCHAR (50) в таблице UTF8.


1
Даже utf8_unicode_ci и utf8_general_ci вызывают ошибку
leuchtdiode

10

Тексты ошибок mysql не очень помогают, в моем случае столбец имел ограничение «not null», поэтому «on delete set null» было запрещено


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
Xmanoux

Это помогло мне пройти дальше, но моя проблема отсутствовала primmary индекса в колонке
Бумеранг

4

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


4

(Последнее обновление) Даже если имя поля и тип данных одинаковы, но параметры сортировки не совпадают, это также приведет к этой проблеме.

Например

    TBL NAME | ТИП ДАННЫХ | COLLATION        

    ActivityID | INT |         latin1_general_ci     ActivityID | INT |         utf8_general_ci

Попробуйте изменить его в

    TBL NAME | ТИП ДАННЫХ | COLLATION        

    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

У меня были такие же проблемы.

Проблема в том, что ссылочный столбец не является первичным ключом.

Сделайте это первичным ключом, и проблема решена.


Это не обязательно должен быть PK, он также может быть UNIQUE NOT NULL.
Philipxy

На самом деле ... в моем случае просто установив его на тип индекса нормально работал.
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

2

Я потерял на это часы!

ПК в одной таблице был utf8в другой был utf8_unicode_ci!


1

Попробуйте запустить следующее:

показать создать таблицу Parent

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

// или проверить кодировки
показать переменные, такие как "character_set_database";
показать переменные типа "collation_database";

// отредактировано: попробуйте что-то вроде этого
ALTER TABLE table2
ADD CONSTRAINT fk_IdTable2
ИНОСТРАННЫЙ КЛЮЧ (Table1_Id)
ССЫЛКИ Table1 (Table1_Id)
ОБ ОБНОВЛЕНИИ КАСКАДА 
НА УДАЛЕННОМ КАСКАДЕ;

9
Попробуйте запустить SHOW ENGINE INNODB STATUS, чтобы получить более подробную информацию об ошибке
Судхир Бастакоти,

@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: Зайдите в таблицу и нажмите на вкладку структуры. Нажмите опцию индексации, чтобы проиндексировать нужный столбец, как показано на скриншоте:

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

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

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

обратите внимание, как zip_code отображается в обеих таблицах.


1

Вам нужно проверить, чтобы оба были одинаковыми по всем своим свойствам, в том числе в «Сличении»


1

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

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


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

1

Я столкнулся с той же проблемой только сейчас. В моем случае все, что мне нужно было сделать, - это убедиться, что таблица, на которую я ссылаюсь во внешнем ключе, должна быть создана до текущей таблицы (ранее в коде). Поэтому, если вы ссылаетесь на переменную (x * 5), система должна знать, что такое x (x должен быть объявлен в предыдущих строках кода). Это решило мою проблему, надеюсь, это поможет кому-то еще.


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

0

У меня была та же проблема с Laravel 5.1 миграцией Schema Builder с MariaDB 10.1.

Проблема была в том, что я набрал unignedвместо unsigned( sписьмо отсутствовало) при настройке столбца.

После исправления опечатка ошибка была исправлена ​​для меня.


0

Даже я столкнулся с той же проблемой с MySQL и liquibase. Итак, вот в чем проблема: таблица, из которой вы хотите сослаться на столбец другой таблицы, отличается либо в случае типа данных, либо с точки зрения размера типа данных.

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 Create», которая создаст код.

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


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 | имя столбца : выберите идентификатор_пользователя | таблица : пользователи | ключ : идентификатор, ...)

Это было просто решено

Джавад Мосави Иран / Урмия

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.