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.