【问题标题】:MySQL Foreign Key Error 1005 errno 150 primary key as foreign keyMySQL Foreign Key Error 1005 errno 150 主键作为外键
【发布时间】:2011-05-03 01:33:47
【问题描述】:

我正在使用 MySQL Workbench 制作一个小型数据库。我有一个名为“Immobili”的主表,它的主键由四列组成:(Comune、Via、Civico、Immobile)。

我还有其他三个表,它们具有相同的主键(Comune、Via、Civico、Immobile),但这些字段也引用到表 Immobili。

第一个问题:我可以制作一个同时是外键的主键吗?

第二个问题:当我尝试导出更改时,它说:

Executing SQL script in server

# ERROR: Error 1005: Can't create table 'dbimmobili.condoni' (errno: 150)

CREATE  TABLE IF NOT EXISTS `dbimmobili`.`Condoni` (

  `ComuneImmobile` VARCHAR(50) NOT NULL ,
  `ViaImmobile` VARCHAR(50) NOT NULL ,
  `CivicoImmobile` VARCHAR(5) NOT NULL ,
  `InternoImmobile` VARCHAR(3) NOT NULL ,
  `ProtocolloNumero` VARCHAR(15) NULL ,
  `DataRichiestaSanatoria` DATE NULL ,
  `DataSanatoria` DATE NULL ,
  `SullePartiEsclusive` TINYINT(1) NULL ,
  `SullePartiComuni` TINYINT(1) NULL ,
  `OblazioneInEuro` DOUBLE NULL ,
  `TecnicoOblazione` VARCHAR(45) NULL ,
  `TelefonoTecnico` VARCHAR(15) NULL ,
  INDEX `ComuneImmobile` (`ComuneImmobile` ASC) ,
  INDEX `ViaImmobile` (`ViaImmobile` ASC) ,
  INDEX `CivicoImmobile` (`CivicoImmobile` ASC) ,
  INDEX `InternoImmobile` (`InternoImmobile` ASC) ,

  PRIMARY KEY (`ComuneImmobile`, `ViaImmobile`, `CivicoImmobile`, `InternoImmobile`) ,

  CONSTRAINT `ComuneImmobile`
    FOREIGN KEY (`ComuneImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`ComuneImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT `ViaImmobile`
    FOREIGN KEY (`ViaImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`ViaImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT `CivicoImmobile`
    FOREIGN KEY (`CivicoImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`CivicoImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,

  CONSTRAINT `InternoImmobile`
    FOREIGN KEY (`InternoImmobile` )
    REFERENCES `dbimmobili`.`Immobile` (`InternoImmobile` )
    ON DELETE CASCADE
    ON UPDATE CASCADE
) ENGINE = InnoDB

显示引擎状态:

表 dbimmobili/valutazionimercato 的外键约束错误:

在被引用的表中找不到索引,其中被引用的列显示为第一列,或者表中的列类型与被引用的表不匹配约束。请注意,使用 >= InnoDB-4.1.12 创建的表中 ENUM 和 SET 的内部存储类型发生了变化,旧表中的此类列不能被新表中的此类列引用。

我哪里做错了?

【问题讨论】:

    标签: mysql mysql-workbench mysql-error-1005


    【解决方案1】:

    创建外键约束时,MySQL 需要在引用表和被引用表上都有一个可用索引。如果引用表上的索引不存在,则会自动创建索引,但被引用表上的索引需要手动创建(Source)。你的好像不见了。

    测试用例:

    CREATE TABLE tbl_a (
        id int PRIMARY KEY,
        some_other_id int,
        value int
    ) ENGINE=INNODB;
    Query OK, 0 rows affected (0.10 sec)
    
    CREATE TABLE tbl_b (
        id int PRIMARY KEY,
        a_id int,
        FOREIGN KEY (a_id) REFERENCES tbl_a (some_other_id)
    ) ENGINE=INNODB;
    ERROR 1005 (HY000): Can't create table 'e.tbl_b' (errno: 150)
    

    但是如果我们在some_other_id上添加一个索引:

    CREATE INDEX ix_some_id ON tbl_a (some_other_id);
    Query OK, 0 rows affected (0.11 sec)
    Records: 0  Duplicates: 0  Warnings: 0
    
    CREATE TABLE tbl_b (
        id int PRIMARY KEY,
        a_id int,
        FOREIGN KEY (a_id) REFERENCES tbl_a (some_other_id)
    ) ENGINE=INNODB;
    Query OK, 0 rows affected (0.06 sec)
    

    这在大多数情况下通常不是问题,因为被引用的字段通常是被引用表的主键,并且主键会自动建立索引。

    【讨论】:

    • 牢记创建索引的顺序,有时您必须更正它。
    • 我发现了一个问题,如果您没有在引用表中提供字段名称,则会导致错误。像FOREIGN KEY (a_id) REFERENCES tbl_a; 甚至在两个表中都有相同名称的字段。
    • 完成CShulz的评论。您必须注意多字段上的索引...您必须检查引用表和被引用表之间的索引定义是否以相同的顺序定义。如果带有 a_id 和 b_id 的 tab_a(引用表)是带有 aa_id 和 b b_id 的 tab_b(引用表)的约束。带有约束绑定:a_id - aa_id 和 b_id - bb_id ...所以如果使用的索引被定义为 tab_a_idx (a_id , b_id) 所以要确保 tab_b idx 是 on (aa_id, bb_id) 而不是 (bb_id, aa_id)
    • 我也遇到了同样的错误。问题最终是我引用的外键具有数据类型“INT unsigned”。我不确定这意味着什么,但将其更改为“INT”是可行的。
    • 遇到了同样的问题。这是由重复的 FK 名称引起的。
    【解决方案2】:

    仔细检查外键是否与您在此表中的字段具有完全相同的类型。例如,两者都应该是 Integer(10) 或 Varchar (8),甚至是字符数。

    【讨论】:

    • 是的,如果假设一张桌子上的键是 tinyint 和另一张桌子上的 int ,即使它们的长度相同,它也会失败
    • 有符号/无符号整数也很重要!感谢您的回答才知道。
    • 我有一个 int 字段引用了一个 bigint 字段。我让它们都一样,它成功了。这个答案在底部。我希望我早点看到它。
    • 即使是 CAN_BE_NULL、UNSIGNED 等标志,两个字段之间的任何细微差别都可能导致此类错误。无论如何 +1 为 danp,这很有帮助
    • 谢谢...这解决了我的问题。我在引用表中有customer_id int(20),在引用表中我有:foreign key(_customer_id) references customer(customer_id) 其中_customer_id 被定义为_customer_id int(10)
    【解决方案3】:

    我意识到这是一篇旧帖子,但它在 Google 中的排名很高,所以我添加了我为我的问题找到的内容。如果你有混合表类型(例如 MyISAM 和 InnoDB),你也会得到这个错误。在这种情况下,InnoDB 是默认的表类型,但是一个表需要全文搜索,所以它被迁移到了 MyISAM。在这种情况下,您无法在引用 MyISAM 表的 InnoDB 表中创建外键。

    【讨论】:

      【解决方案4】:

      如果您的键是 CHAR/VARCHAR 或类似类型,另一个可能的问题是排序规则不同。检查字符集是否相同。

      【讨论】:

      • 这就是我的原因。以为我将默认的latin1_swedish_ci 更改为utf8_unicode_ci,但点击错误utf8mb4_unicode_ci
      【解决方案5】:

      我遇到了这个错误,并在我的案例中找到了错误的原因。 我仍在回复这篇旧帖子,因为它在 Google 上的排名很高。

      我要链接的两个列的变量都是整数,但其中一个整数已选中“无符号”。只需取消选中即可修复我的错误。

      【讨论】:

        【解决方案6】:

        我遇到了同样的错误。我发现我在主表中将主键创建为 BIGINT UNSIGNED 并在第二个表中将其声明为外键的解决方案仅为 BIGINT。

        当我在第二个表中将我的外键声明为 BIGINT UNSIGED 时,一切正常,甚至不需要创建任何索引。

        所以这是主键和外键之间的数据类型不匹配:)

        【讨论】:

        • 另请注意,即使数据类型相同,表之间的不同排序规则也会导致此问题。
        【解决方案7】:

        我遇到了完全相同的问题,但我的问题的解决方案完全不同。我在数据库的其他地方有一个同名的外键。这导致了错误 1005。

        将我的外键重命名为更具体的内容解决了这个问题。

        【讨论】:

          【解决方案8】:
          1. 确保两个表使用相同的引擎类型。
          2. 确保要索引的字段具有相同的类型和长度。

          【讨论】:

            【解决方案9】:

            在我的情况下,错误是由于referencing 表是MyISAMreferring 表是InnoDB

            MyISAM to InnoDBConverted 表引擎为我解决了这个问题。

            ALTER TABLE table_name ENGINE=InnoDB;
            

            【讨论】:

            • 我有同样的错误,奇怪的 MySql 没有给出一个错误提示那个方向。我建议从同步使用表的查询开始,以便为引擎 (InnoDB)、字符集 (utf8) 和排序 (utf8_general_ci) 设置相同的值。始终检查所有列名的创建查询是否使用相同的 CamelCase(小写)。检查您的主键、键和约束。
            【解决方案10】:

            我还没有声望支持史蒂夫的建议,但它解决了我的问题。

            就我而言,我收到此错误是因为使用不同的数据库引擎创建的两个表——一个是 Innodb,另一个是 MyISAM。

            您可以使用以下方法更改数据库类型:ALTER TABLE t ENGINE = MISAM;

            @见http://dev.mysql.com/doc/refman/5.1/en/storage-engine-setting.html

            【讨论】:

              【解决方案11】:

              在创建表时要注意 CHARSETCOLLATE 参数。 在外键方面类似这样的问题:

              CREATE TABLE yourTableName (
              ....
              ....
              ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
              

              在我的情况下,我无法使用 FOREIGN KEY 引用创建表。首先,我得到了几乎什么也没说的错误代码 1005。然后我添加了 COLLATE,最后是抱怨 CHARSET 的错误消息。

              Error Code: 1253. COLLATION 'utf8_unicode_ci' is not valid for CHARACTER SET 'latin1'
              

              修正后我的问题解决了。

              【讨论】:

                【解决方案12】:

                这不是您的具体情况,但对于其他人来说,值得注意的是,如果您尝试引用表中的某些字段而不是该表的整个主键,则可能会发生此错误。显然这是不允许的。

                【讨论】:

                  【解决方案13】:

                  如果有人在 FK/PK 关系看似良好的情况下出现此错误,并且您使用了可视化工具,请尝试删除有问题的 fk 列并将它们重新添加到工具中。我不断收到此错误,直到我重新绘制了清除问题的连接。

                  【讨论】:

                    【解决方案14】:

                    当主键有 2 列时,它们构成复合主键,因此您必须确保在被引用的表中也有 2 列具有相同的数据类型。

                    【讨论】:

                      【解决方案15】:

                      对我来说,我试图将子表中的常规索引字段与父表中的主键匹配,并且默认情况下,一些 MySQL 前端 GUI(如 Sequel Pro)将主键设置为无符号,所以你有确保子表字段也未签名(除非这些字段可能包含负整数,否则请确保它们都已签名)。

                      【讨论】:

                        【解决方案16】:

                        第一个问题:我可以制作一个同时是外键的主键吗?

                        是的。事实上,对于 MySQL 工作台,我已经养成了只使用主键作为外键的习惯。确实减少了收到的随机错误,例如问题中所述的 err:150。

                        # ERROR: Error 1005: Can't create table 'dbimmobili.condoni' (errno: 150)

                        这确实与索引有关,或者更具体地说,MySQL 工作台如何解释和使用它们。如果你在同一个正向工程操作中对模型进行了很多更改(例如外键、索引、col 顺序),这真的会让人感到困惑,尤其是如果另一端已经有数据库。例如,我不认为自动创建的索引在删除外键后会自动删除。

                        这是我为解决您收到的错误所做的。请注意,这似乎很麻烦,但与我使用其他方法所花费的时间相比,它不是。

                        1.将查找表中的所有外键设为主键(1中的1对多)。

                        在我的例子中,这涉及将 id 作为 pk 更改为 tbl_users 中的用户名,更改为 tbl_companies 中的用户名 AND 公司,以及 tbl_company_contacts 中的用户名和公司和联系人。它是一个多用户输入多个公司联系人的应用程序,允许重叠和隐藏其他用户的联系人。

                        2。删除所有图表关系和所有非主键的表索引。

                        这修复了大多数实际上由有问题的 MySQL 工作台引起的索引问题。

                        3。如果您从头到尾执行此操作,请将模式放在服务器上,这样 mysql 工作台就不会对现有索引感到困惑,也不会在模型中缺少索引(问题是由 bby 索引和外键关系引起的,而不仅仅是索引)。

                        这减少了数据库、服务器和 Mysql 工作台必须做出的大量决策。这些关于如何进行正向工程的决策既复杂又智能,但并不完美。

                        4.现在,我认为这又回到了原点(通常是在设计太快而没有分步过程之后)。我仍然有所有的桌子,但在这个阶段它们是干净的。现在你只需:

                        首先,前向工程只是为了确保表(没有关系)按预期工作。

                        通过主键沿着关系链向下,从最顶层的表开始(我的例子是 tbl_users 到 tbl_companies)。在每个关系之后,始终进行正向工程以确保它运行,然后保存模型并关闭,然后对模型进行逆向工程以确保它运行。这使您可以在问题出现时快速隔离问题,在我的情况下,旧的已删除外键使用的遗留索引(发生了 2-3 次)。

                        还有 tadda,回到你需要去的地方。

                        【讨论】:

                          【解决方案17】:

                          MySQL 是出了名的脾气暴躁,尤其是在外键和触发器方面。我现在正在微调一个这样的数据库,并遇到了这个问题。它不是不言自明或直观的,所以这里是:

                          除了检查要在关系中引用的两列是否具有相同的数据类型外,还必须确保要引用的表上的列是索引。如果您使用的是 MySQL Workbench,请选择“列”旁边的“索引”选项卡,并确保外键引用的列是索引。如果没有,请创建一个,将其命名为有意义的名称,并将其类型设为“INDEX”。

                          一个好的做法是清理关系中涉及的表,以确保之前的尝试没有创建您不想要或不需要的索引。

                          我希望它有所帮助,一些 MySQL 错误令人抓狂。

                          【讨论】:

                            猜你喜欢
                            • 1970-01-01
                            • 2018-04-14
                            • 1970-01-01
                            • 2021-08-06
                            • 2012-10-17
                            • 2020-08-11
                            • 2016-07-27
                            • 2015-06-20
                            • 2020-08-07
                            相关资源
                            最近更新 更多