MySQL外键错误1005错误150

时间:2010-10-31 12:51:00

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

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

现在,我还有另外三个表,它们具有相同的主键(Comune,Via,Civico,Immobile),但这些字段也引用了表Immobili。

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

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

中执行SQL脚本
# 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的外键约束出错:

     

在引用的表中找不到引用列作为第一列的索引,       表中的列或列,并且引用的表与约束不匹配。请注意,在使用> =创建的表中,ENUM和SET的内部存储类型已更改       InnoDB-4.1.12和旧表中的此类列不能被这些列引用       在新表中。

我做错了什么?

17 个答案:

答案 0 :(得分:50)

创建外键约束时,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)

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

答案 1 :(得分:30)

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

答案 2 :(得分:15)

我意识到这是一个老帖子,但它在谷歌中排名很高,所以我添加了我想出的问题。如果您有多种表格类型(例如MyISAM和InnoDB),您也会收到此错误。在这种情况下,InnoDB是默认的表类型,但是一个表需要全文搜索,因此它被迁移到MyISAM。在这种情况下,您无法在InnoDB表中创建引用MyISAM表的外键。

答案 3 :(得分:9)

如果您的密钥是CHAR / VARCHAR或类似的东西,另一个可能的问题是不同的整理。检查字符集是否相同。

答案 4 :(得分:6)

我遇到了这个错误,并在我的案例中找到了错误的原因。 我还在回答这个老帖子,因为它在谷歌上排名很高。

我想要链接的两个列的变量都是整数,但其中一个整数已经未签名'检查。只需取消选中即可修复错误。

答案 5 :(得分:5)

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

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

因此,主键和外键之间的数据类型不匹配:)

答案 6 :(得分:4)

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

将我的外键重命名为更适合该情况的内容解决了这个问题。

答案 7 :(得分:3)

  1. 确保两个表使用相同的引擎类型。
  2. 确保您要编制索引的字段具有相同的类型和长度。

答案 8 :(得分:3)

在我的情况下,错误是由于referencing表格为MyISAM,而referring表格为InnoDB

来自Converted

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

ALTER TABLE table_name ENGINE=InnoDB;

答案 9 :(得分:1)

我还没有声名鹊起Steve的建议,但它解决了我的问题。

在我的情况下,我收到此错误,因为使用不同数据库引擎创建的两个表 - 一个是Innodb,另一个是MyISAM。

您可以使用以下命令更改数据库类型:ALTER TABLE t ENGINE = MYISAM;

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

答案 10 :(得分:1)

创建表时,请注意 CHARSET COLLATE 参数。 就FOREIGN KEY 问题而言:

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'

经过纠正后,我的问题得到了解决。

答案 11 :(得分:0)

如果有任何人在看似格式良好的FK / PK关系中出现此错误并且您使用了可视化工具,请尝试删除有问题的fk列并在工具中重新添加它们。我不断得到这个错误,直到我重新清除了解决问题的连接。

答案 12 :(得分:0)

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

答案 13 :(得分:0)

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

答案 14 :(得分:0)

对我来说,我试图将子表中的常规索引字段与父表中的主键进行匹配,默认情况下,一些像Sequel Pro这样的MySQL前端GUI将主键设置为unsigned,因此您有确保子表字段也是无符号的(除非这些字段可能包含负的int,然后确保它们都已签名)。

答案 15 :(得分:0)

众所周知,MySQL非常暴躁,特别是在外键和触发器方面。我现在正在调整一个这样的数据库,并遇到了这个问题。这不是自明的或直观的,所以在这里:

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

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

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

答案 16 :(得分:0)

  

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

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

  

#ERROR:错误1005:无法创建表'dbimmobili.condoni'(错误号:150)

这确实与索引有关,或者更具体地说,MySQL工作台如何解释和使用它们。如果你在同一个正向工程操作中改变模型中的很多东西(例如外键,索引,col命令),那真的很困惑,,特别是如果另一端已有数据库。例如,我不认为自动创建的索引在删除外键后会自动删除。

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

<强> 1。在查找表中创建所有外键主键(1到1中的1)。

在我的情况下,这包括将tb更改为tbl_users中的用户名,tbl_companies中的用户名和公司,以及tbl_company_contacts中的用户名AND公司AND联系人。这是一个供多个用户输入多个公司联系人的应用程序,允许重叠和隐藏其他用户联系人。

<强> 2。删除所有不是主键的图表关系和所有表索引。

这解决了大多数真正由错误的MySQL工作台引起的索引问题。

第3。如果你从头到尾这样做,请将模式放在服务器上,这样mysql工作台就不会对现有索引感到困惑,并且在模型中没有关闭(问题是由于bby索引和外键关系,而不是索引)。

这减少了DB,服务器和Mysql工作台必须做出的很多决定。这些关于如何推进工程设计的决定既复杂又聪明,但并不完美。

<强> 4。现在,我认为这回到原点(通常在没有阶梯式处理的情况下设计得太快)。我仍然拥有所有的桌子,但在这个阶段他们很干净。现在你只是:

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

通过主键关注关系链,从最顶层的表开始(我的情况是tbl_users到tbl_companies)。在每次关系之后,始终转发工程师确保运行,然后保存模型并关闭,然后对模型进行反向工程以确保 。这允许您快速隔离出现的问题,在我的情况下留下旧的删除外键使用的索引(发生2-3次)。

tadda,回到你需要的地方。