mysql外键约束格式错误


173

我有两个表,table1是一列父表ID,并table2与一列IDFromTable1(而不是实际的名称),当我把一个FK上IDFromTable1,以IDtable1我得到的错误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什么?
罗曼(Romain)

5
另外,检查两个表的字符集是否相同。
卡斯滕

两个表引擎都是innoDB。不知道在哪里可以找到字符集,并且都是字符类型。该ID是table1中的主键
user516883 2011年

2
请提供表1和表2的表定义。您是怎么得到这个错误的?您是否使用工具来创建外键?看来这不是MySQL本机错误。
Devart

@ user516883-您需要帮助来获取表定义吗?在HeidiSQL中,您只需单击“ 创建代码”选项卡。
阿尔瓦罗·冈萨雷斯

Answers:


422

我在HeidiSQL中遇到了同样的问题。您收到的错误非常神秘。我的问题最终是外键列和引用列的类型或长度不同。

外键列为SMALLINT(5) UNSIGNED,引用列为INT(10) UNSIGNED。一旦将它们设置为完全相同的类型,外键创建便可以完美工作。


58
或者可能是所引用的列不是主键
nawfal 2014年

9
对我来说有点类似的问题-引用的表还不存在。哎呀
Amalgovinus 2014年

5
我已经完全了解了Jake的工作,但是在HeidiSQL上遇到了另一个FK问题(不同类型)。varchars上的FK必须是相同的排序规则。希望以后能对别人有所帮助!
cbloss793

10
以我为例,这是因为编码和排序规则不同。
哈特里

1
@nawfal-我认为它不一定必须是主键,但必须具有索引。主键自动获得索引。
伊泰市

48

使用MyISAM引擎创建父表时,我遇到了同样的问题。我解决了一个愚蠢的错误:

ALTER TABLE parent_table ENGINE=InnoDB;

非常感谢,我为此而发疯。知道为什么数据库会突然切换表的引擎吗?
罗伯特·富兰克林

28

确保列相同(相同类型),如果引用列不同primary_key,则确保相同INDEXED


我什至碰巧,没有错误,但是没有添加外键(实际上是1,实际上不是1),但是KEY referencing_column(referencing_column) 两个外键定义之前添加简单之后,它们都成功添加了:)
jave.web

2
没有索引的键是我的问题。
Neil Masters

1
我遇到了这个问题,问题是我有一个双列主键,并且您不能将主键的第二列用作外键。因此,我只为主键的第二列添加了自己的索引,然后它起作用了。
Firze

21

定义外键的语法非常宽容,但是对于任何涉足此方法的人来说,外键必须是“相同类型”的事实甚至适用于排序规则,不仅适用于数据类型,长度和位签名。

不是要在模型中混合排序规则(可以吗?),但是如果要这样做,请确保您的主键和外键字段在phpmyadmin或Heidi SQL中使用相同的排序规则类型。

希望这可以节省您四个小时的反复试验,而这会花费我很多时间。


1
谢谢!事实证明,我的在线主机使用ISAM引擎,对于本地开发人员,我使用InnoDB。当我从主机向本地备份表时...繁荣。
2013年

MariaDB的最新版本似乎使用utf8_mb4作为默认字符集(当未在服务器配置中显式设置时),COLLATE utf8mb4_unicode_ci我的(意外)问题(在开发机上)也是如此。
JonnyJD

13

我有同样的问题,但解决了。

只要确保“ table1”中的“ ID”列具有唯一索引!

当然,这两个表中“ ID”和“ IDFromTable1”列的类型,长度也必须相同。但是您已经知道了这一点。


你让我今天一整天都感觉很好。
kevenlolo

1
乐意效劳!;)
Renat Gatin18年

不确定细节,但是我有一个带有此错误的复合键,该键通过为列添加单独的唯一索引而得以修复。
Halvor Holsten Strand'1

被引用的列必须被索引,它不必是唯一的(尽管这是通常的情况)。
Barmar

10

只是为了完成。

如果您具有带有VARCHAR(..)的外键,并且所引用表的字符集与引用该表的表的字符集不同,则可能发生此错误。

例如Latin1表中的VARCHAR(50)与UTF8表中的VARCHAR(50)不同。


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

这确实帮助我进一步通过,但是我的问题是缺少列中的主要索引
bumerang

4

显示此错误的另一个可能原因。我创建表的顺序是错误的。我试图从尚未创建的表中引用键。


4

(最近发送)即使字段名称和数据类型相同但排序规则也不相同,也会导致该问题。

例如

    TBL名称| 数据类型| 集合        

    ActivityID | INT |         latin1_general_ci     活动ID | INT |         utf8_general_ci

尝试将其更改为

    TBL名称| 数据类型| 集合        

    ActivityID | INT |         latin1_general_ci     活动ID | INT |         latin1_general_ci

....

这对我有用。


3

检查表引擎,两个表必须是同一引擎,这对我有很大帮助。


好点子!我正在处理MySQL中的Zen Cart数据库,默认情况下其表都在MyISAM引擎中。我使用InnoDB引擎添加了一个表,并尝试将一个外键约束从我的表添加到核心Zen Cart。它因出现这种模糊的“格式错误”错误而失败。您可以通过SHOW TABLE STATUS LIKE 'table_name';
Neek 18'Mar

2

我有同样的问题。

问题是参考列不是主键。

将其设为主键即可解决问题。


它不必是PK,也可以是UNIQUE NOT NULL。
philipxy

实际上...就我而言,只需将其设置为正常的索引类型即可。
hendr1x

2

尽管其他答案非常有帮助,但也想分享我的经验。

当我删除一个id已经被其他表(带有data)作为外键引用的表并尝试使用其他一些列重新创建/导入该表时,我遇到了这个问题。

用于重新创建的查询(在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)类型, 
它是行不通的),并且,如果它们是整数,则应无符号。

//或检查字符集
显示类似“ character_set_database”的变量;
显示像“ collat​​ion_database”这样的变量;

//编辑:尝试类似这样的方法
ALTER TABLE table2
添加约束fk_IdTable2
外键(Table1_Id)
参考Table1(Table1_Id)
更新级联 
删除级联时;

9
尝试运行SHOW ENGINE INNODB STATUS以获取有关该错误的更多详细信息
Sudhir Bastakoti 2011年

@SudhirBastakoti-+1!对我来说就做到了。详细信息很有帮助。能够快速解决问题。
保罗·卡尔顿

1

我在Symfony 2.8中遇到了同样的问题。

我一开始没有得到,因为外键的int长度等没有类似的问题。

最后,我必须在项目文件夹中执行以下操作。(服务器重新启动没有帮助!)

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


1

感谢S Doerin:

“仅是为了完成。如果您具有带有VARCHAR(..)的外键,并且所引用表的字符集与引用该表的字符集不同,则可能会出现这种错误。例如,Latin1表中的VARCHAR(50)是与UTF8表中的VARCHAR(50)不同。”

我解决了这个问题,更改了表的字符类型。创建的文件有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

我在使用MariaDB 10.1的Laravel 5.1迁移架构生成器时遇到了相同的问题。

问题是在设置列时我键入unigned而不是unsigneds字母丢失)。

修正错字错误后,对我来说是固定的。


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创建”以创建代码。

在此处输入图片说明


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');
        });

第二张表的ID的数据类型必须为增量


0

这个问题很容易解决

例如:您有两个表,分别命名为用户帖子,并且要在帖子中创建外键表中并使用phpMyAdmin

1)在表中添加新列名称:use_id | 类型:喜欢的ID用户表| 长度:喜欢的ID用户表| 默认值:NULL | 属性:无符号|指数:INDEX)

2)在“ 结构”选项卡上转到关系视图约束名:由phpmyAdmin自动设置| 列名:选择user_id | :users | key:id,...)

简单解决了

Javad Mosavi伊朗/ urmia

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.