MySQL:无法创建表(错误号:150)
Posted
技术标签:
【中文标题】MySQL:无法创建表(错误号:150)【英文标题】:MySQL: Can't create table (errno: 150) 【发布时间】:2014-08-09 06:21:01 【问题描述】:我正在尝试导入 .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,但一种是无符号的,而另一种不是 在使用模式生成器时,我经常遇到BIGINT
和 INT
。
当外键不是 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】:我有同样的问题。它与表格的列Collation和Character Set有关。 确保 Character Set 和 Collation 对于两个表的两列必须相同。如果你想在上面设置一个外键。 示例 - 如果您将外键放在 userImage 表的 userID 列上,引用用户表的 userID 列。那么排序规则必须相同,即 utf8_general_ci 和字符集 utf8 的两列表。一般在创建表时mysql会从服务器设置中获取这两个配置。
【讨论】:
为什么我以前没有看到这个帖子!?我花了一个小时找出根本原因。就我而言,这是字符集。引用表和引用表必须具有相同的字符集。【参考方案11】:在浏览了上面的答案并进行了一些实验之后,这是解决 MySQL 中的外键错误(1005 - 错误 150)的有效方法。
为了正确创建外键,MySQL 要求的是:
所有引用的键都必须有 PRIMARY 或 UNIQUE 索引。 再次引用列必须具有与引用列相同的数据类型。满足这些要求,一切都会好起来的。
【讨论】:
【参考方案12】:我在将 Windows 应用程序移植到 Linux 时遇到了这个错误。在 Windows 中,数据库表名不区分大小写,而在 Linux 中,它们区分大小写,可能是因为文件系统不同。因此,在 Windows 表上 Table1
与 table1
相同,在 REFERENCES
中,table1
和 Table1
都有效。在 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)的主要内容,如果未能解决你的问题,请参考以下文章