MySQL:无法创建表(错误号:150)

Posted

技术标签:

【中文标题】MySQL:无法创建表(错误号:150)【英文标题】:MySQL: Can't create table (errno: 150) 【发布时间】:2016-02-11 15:10:18 【问题描述】:

我正在尝试导入 .sql 文件,但它在创建表时失败。

这是失败的查询:

CREATE TABLE `data` (
`id` int(10) unsigned NOT NULL,
`name` varchar(100) NOT NULL,
`value` varchar(15) NOT NULL,
UNIQUE KEY `id` (`id`,`name`),
CONSTRAINT `data_ibfk_1` FOREIGN KEY (`id`) REFERENCES `keywords` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;    

我从同一个数据库中导出了 .sql,我删除了所有表,现在我尝试导入它,为什么会失败?

mysql:无法创建表 './dbname/data.frm'(错误号:150)

【问题讨论】:

对于这个错误的所有原因,这里有一个详尽的资源,说明了 MySQL 中导致 errno 150(和 errno 121/其他外键错误)的原因。 我发现列必须相同(即使无符号标志也必须匹配)。 @JohnSmith ...在哪里? 我建议阅读这篇列出 10 个可能原因的博文:verysimple.com/2006/10/22/… @CharlesWood:“John Smith... 已于 2013 年 4 月 6 日 19:29 看到”,即您发表评论前大约三个月。我有一种恐惧,在这个沉闷的世界结束之前,“哪里”的谜团不会被揭开! :> 【参考方案1】:

来自MySQL - FOREIGN KEY Constraints Documentation:

如果您重新创建已删除的表,则它必须具有符合引用它的外键约束的定义。它必须具有正确的列名和类型,并且必须在引用的键上具有索引,如前所述。 如果不满足这些,MySQL 会返回 Error 1005 并在错误消息中引用 Error 150,这意味着没有正确形成外键约束。 同样,如果由于错误 150,ALTER TABLE 失败,这意味着为更改的表形成的外键定义将不正确。

【讨论】:

一张表中的两列能否引用另一张表中的一列,在哪里是PK? @Eugene:两列中的每一列都可以与另一个表中的 PK 有外键关系——而不是两列作为单个外键关系。 @OMGPonies:感谢您回答这个问题!..我正在寻找它...我也在这里问了一个问题***.com/questions/13487010/… ....虽然我有一些很好的答案,但我想符合Whether its possible to write Nested Query for my problem? ..我也请你回答我! 我的错误是主表有 MyISAM 和子表 InnoDB 引擎。当前的 create.sql 脚本对所有表都使用 InnoDB,但我的安装非常旧,第一个脚本使用 MyISAM。 @Whome - 是的,在这里遇到了同样的问题。【参考方案2】:

错误 150 表示您的外键有问题。可能外表上的键不是完全相同的类型?

【讨论】:

谢谢 :) 对我来说,数据类型是 INT,但一种是无符号的,而另一种不是 在使用模式生成器时,我经常遇到 BIGINTINT 当外键不是 INT 值时,我遇到了同样的问题。当外键引用该列时,该列必须是唯一的。 根据the documentation,如果引用列上没有索引(并且引用列必须首先出现在索引中),则会出现同样的错误。【参考方案3】:

您可以通过运行SHOW ENGINE INNODB STATUS; 然后在输出中查找LATEST FOREIGN KEY ERROR 来获得实际的错误消息。

来源:answer from another user in a similar question

【讨论】:

这其实很有用。它会告诉您确切的错误。 谢谢。很遗憾 MySQL Workbench 没有使用它。 太棒了。这很有帮助。告诉你确切的错误。我的是,已将列设为 NULLABLE,但已设置“删除集为空”。非常感谢。 如果你在你的服务器上有权限:(【参考方案4】:

数据类型必须完全匹配。如果您正在处理 varchar 类型,则表必须使用相同的排序规则。

【讨论】:

感谢整理位。【参考方案5】:

我认为所有这些正确的答案都会误导问题。

如果您要使用外键恢复转储文件,实际的答案是在您开始恢复之前:

SET FOREIGN_KEY_CHECKS=0;

因为在外部表甚至存在之前,还原自然会创建一些约束。

【讨论】:

这样做对我不起作用,仍然给出错误。有什么想法吗?【参考方案6】:

在某些情况下,如果相关表之间存在不同的引擎,您可能会遇到此错误消息。例如,一个表可能使用 InnoDB,而另一个表使用 MyISAM。两者必须相同

【讨论】:

谢谢 - 这是我的问题。 那是我的问题。谢谢 如果您使用 mysqldump 创建了一个 innodb 表的 sql 文件,并且它们被导出为 myisam talbes,则可能会发生这种情况。【参考方案7】:

错误号150 表示外键约束失败。您可能在外键所依赖的表(表keywords)之前创建此表。首先创建该表,它应该可以正常工作。

如果没有,请删除外键语句并在创建表后添加 - 您将收到有关特定约束失败的更有意义的错误消息。

【讨论】:

【参考方案8】:

有很多事情会导致 errno 150,所以对于搜索这个主题的人,我认为这是一个接近详尽的列表(来源 Causes of Errno 150):

对于 errno 150 或 errno 121,只需输入 SHOW ENGINE INNODB STATUS,就会有一个名为“LATEST FOREIGN KEY ERROR”的部分。在此之下,它会给您一个非常有用的错误消息,通常会立即告诉您问题所在。你需要超级权限才能运行它,所以如果你没有,你只需要测试以下场景。

1) 数据类型不匹配:列的类型必须相同

2) 父列未编入索引(或索引顺序错误)

3) 列排序规则不匹配

4) 在 NOT NULL 列上使用 SET NULL

5) 表排序规则不匹配:即使列排序规则匹配,在某些 MySQL 版本上这也可能是个问题。

6) 父列实际上并不存在于父表中。检查拼写(可能在列的开头或结尾留一个空格)

7) 其中一列的索引不完整,或者该列对于完整索引来说太长。请注意,MySQL(除非您对其进行调整)的最大单列键长度为 767 字节(这对应于 varchar(255) UTF 列)

如果您收到 errno 121,有以下几个原因:

1) 您选择的约束名称已被占用

2) 在某些系统上,如果您的语句和表名存在大小写差异。如果您从一台服务器转到具有不同案例处理规则的另一台服务器,这可能会咬到您。

【讨论】:

在某些版本中,如果表不是 innodb,您会得到 errno 150,但在某些版本中,它只是静默失败。 谢谢,这太棒了:| ------------------------------------ |最新的外键错误 | ------------------------------------ |您已经定义了一个 SET NULL 条件,尽管有些 |列被定义为 NOT NULL。 我有这个错误,因为父表已分区。【参考方案9】:

有时 MySQL 只是超级愚蠢——我可以理解外键的原因。但就我而言,我刚刚删除了整个数据库,但我仍然得到错误...为什么?我的意思是,没有数据库了......我正在使用的 sql 用户无法访问服务器上的任何其他数据库......我的意思是,服务器对于当前用户来说是“空的”,我仍然得到这个错误?抱歉,我猜 MySQL 是在骗我……但我可以处理它:) 只需在你该死的语句周围添加这两行 SQL:

SET FOREIGN_KEY_CHECKS = 0;
# some code that gives you errno: 150
SET FOREIGN_KEY_CHECKS = 1;

现在应该执行 sql...如果您确实有外键问题,它会在您将再次启用检查的行显示给您 - 这将失败.. 但我的服务器只是安静:)

【讨论】:

如果列和它所引用的列之间实际上存在差异,这可能会导致问题。例如。假设引用的列是 varchar(200) 而引用者是 varchar(50),那么当尝试级联时,可能会出现奇怪的行为。我还没有遇到因为数据不匹配而发出 errno 150 的问题。 有趣的见解@juacala :) 对我来说很有趣的是,每当我遇到这个问题时,我的方法总是修复它......至少直到今天 :D 但我们永远不会停止学习,对吧;) 这实际上帮助我生成了脚本 liquibase。该脚本在 MySQL > 5.5 上完美运行,但在 5.1 版上运行失败。【参考方案10】:

我有同样的问题。它与表格的列Collat​​ionCharacter Set有关。 确保 Character SetCollat​​ion 对于两个表的两列必须相同。如果你想在上面设置一个外键。 示例 - 如果您将外键放在 userImage 表的 userID 列上,引用用户表的 userID 列。那么排序规则必须相同,即 utf8_general_ci 和字符集 utf8 的两列表。一般在创建表时mysql会从服务器设置中获取这两个配置。

【讨论】:

为什么我以前没有看到这篇文章!?我花了一个小时找出根本原因。就我而言,这是字符集。引用表和引用表必须具有相同的字符集。【参考方案11】:

在浏览了上面的答案并进行了一些实验之后,这是解决 MySQL 中的外键错误(1005 - 错误 150)的有效方法。

为了正确创建外键,MySQL 要求的是:

所有引用的键都必须有 PRIMARY 或 UNIQUE 索引。 再次引用列必须具有与引用列相同的数据类型。

满足这些要求,一切都会好起来的。

【讨论】:

【参考方案12】:

我在将 Windows 应用程序移植到 Linux 时遇到了这个错误。在 Windows 中,数据库表名不区分大小写,而在 Linux 中它们区分大小写,可能是因为文件系统不同。因此,在 Windows 表上 Table1table1 相同,在 REFERENCES 中,table1Table1 都有效。在 Linux 上,当应用程序在创建数据库结构时使用 table1 而不是 Table1 时,我看到了错误 #150;当我在Table1 引用中做出正确的字符大小写时,它也开始在 Linux 上工作。因此,如果没有其他帮助,请确保在REFERENCES 在 Linux 上使用正确的表名字符大小写。

【讨论】:

这也是我的情况!将脚本从不区分大小写 (OS X) 移动到区分大小写的 mysql 版本 (Debian)。【参考方案13】:

通常,外键和主键不匹配会导致 错误:150。

外键必须与主键具有相同的数据类型。此外,如果主键无符号,那么外键也必须是无符号

【讨论】:

【参考方案14】:

更改表的引擎,只有 innoDB 支持外键

【讨论】:

【参考方案15】:

如果 PK 表是在一个 CHARSET 中创建的,然后您在另一个 CHARSET 中创建 FK 表。那么您也可能会收到此错误...我也遇到此错误,但在更改字符集后到 PK 字符集,然后它被执行而没有错误

create table users
(
------------
-------------
)DEFAULT CHARSET=latin1;


create table Emp
(
---------
---------
---------
FOREIGN KEY (userid) REFERENCES users(id) on update cascade on delete cascade)ENGINE=InnoDB, DEFAULT CHARSET=latin1;

【讨论】:

【参考方案16】:

如果两个表有引用,则可能会出现此错误,例如,一个表是 Student,另一个表是 Education,并且我们希望 Education 表具有 Student 表的外键引用。在这种情况下,两个表的列数据类型应该相同,否则会产生错误。

【讨论】:

【参考方案17】:

在大多数情况下,问题是由于 ENGINE 差异造成的。如果父表是由 InnoDB 创建的,那么引用的表应该由 MyISAM 创建,反之亦然

【讨论】:

【参考方案18】:

就我而言。我的引擎和字符集有问题,因为我的托管服务器更改设置并且我的新表是 MyISAM,但我的旧表是 InnoDB。只是我变了。

【讨论】:

这对我来说是正确的,因为我正在修改一个不是我制作的数据库。【参考方案19】:

请确保您的主键列和引用列具有相同的数据类型和属性(无符号、二进制、无符号填零等)。

【讨论】:

【参考方案20】:

真正的边缘案例是您使用 MySQL 工具(在我的案例中为 Sequel Pro)重命名数据库。然后创建了一个同名的数据库。

这使外键约束保持到相同的数据库名称,因此重命名的数据库(例如 my_db_renamed)在新创建的数据库 (my_db) 中具有外键约束

不确定这是否是 Sequel Pro 中的错误,或者某些用例是否需要这种行为,但它花费了我一大早:/

【讨论】:

【参考方案21】:

我有同样的错误。在我的例子中,错误的原因是我在约束中有一个 ON DELETE SET NULL 语句,而我在其定义中放置约束的字段有一个 NOT NULL 语句。在字段中允许 NULL 解决了这个问题。

【讨论】:

【参考方案22】:

我在从文本文件创建数据库时遇到了这种问题。

mysql -uroot -padmin < E:\important\sampdb\createdb.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\create_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\create_absence.sql

mysql -uroot -padmin sampdb < E:\important\sampdb\insert_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\insert_absence.sql

mysql -uroot -padmin sampdb < E:\important\sampdb\load_student.sql
mysql -uroot -padmin sampdb < E:\important\sampdb\load_absence.sql 

我刚刚在Create.bat中写了以上几行并运行了bat文件。

我的错误在于我的 sql 文件中的执行顺序。我试图用主键和外键创建表。在运行时,它将搜索参考表,但表不存在。 所以它会返回那种错误。

如果您使用外键创建表,请检查参考 表是否存在。并检查参考的名称 表格和字段。

【讨论】:

换句话说,您试图创建一个表,其外键指向另一个尚不存在的表。以正确的顺序创建表格以解决问题。【参考方案23】:

我遇到了类似的问题,但我的问题是因为我正在向具有数据的现有表添加一个新字段,并且新字段引用父表中的另一个字段并且还具有 NOT NULL 的定义并且没有任何 DEFAULT价值观。 - 我发现事情不工作的原因是因为

    我的新字段需要在每个记录上使用父表中的值自动填充空白字段,然后才能应用约束。每次应用约束时,都需要保持表数据的完整性不变。实施约束(外键)但有一些数据库记录没有父表中的值将意味着数据已损坏,因此 MySQL 永远不会强制执行您的约束

请务必记住,在正常情况下,如果您提前计划好数据库,并在数据插入之前实施约束,则可以避免这种特殊情况

避免这个问题的更简单的方法是

保存您的数据库表数据 截断表数据(和表工件,即索引等) 应用约束 导入您的数据

我希望这对某人有帮助

【讨论】:

【参考方案24】:

创建没有外键的表,然后单独设置外键。

【讨论】:

【参考方案25】:

也许this 会有所帮助?主键列的定义要和外键列完全一样。

【讨论】:

【参考方案26】:

确保所有表都可以支持外键-InnoDB引擎

【讨论】:

【参考方案27】:

您从子表中引用的 PARENT 表的列必须是唯一的。如果不是,则导致错误 150。

【讨论】:

可能值得您添加更多细节 - 例如特定的列和表名【参考方案28】:

在使用单个表转储 Django mysql 数据库时,我遇到了类似的问题。我能够通过将数据库转储到文本文件、使用 emacs 将有问题的表移动到文件末尾并将修改后的 sql 转储文件导入新实例来解决问题。

HTH 乌韦

【讨论】:

【参考方案29】:

我已通过使变量接受 null 来纠正问题

ALTER TABLE `ajout_norme` 
CHANGE `type_norme_code` `type_norme_code` VARCHAR( 2 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL

【讨论】:

【参考方案30】:

我在执行一系列 MySQL 命令时遇到了同样的问题。我在创建表期间将外键引用到尚未创建的其他表时发生。就是引用前表存在的顺序。

解决方法:先创建父表,再创建具有外键的子表。

【讨论】:

以上是关于MySQL:无法创建表(错误号:150)的主要内容,如果未能解决你的问题,请参考以下文章

MySQL:无法创建表(错误号:150)

MySQL:无法创建表(错误号:150)

MySQL:无法创建表(错误号:150)

MySQL:无法创建表(错误号:150)

MySQL 外键,无法创建表(错误号:150)

使用 mysql 工作台创建 CHAR 类型的外键时出错:错误 1005:无法创建表(错误号:150)