错误代码:1005。无法创建表'...'(错误号:150)

107

我在互联网上搜索了解决这个问题的方法,并查看了Stack Overflow的问题,但没有一种解决方案适用于我的情况。

我想从表sira_no创建一个指向metal_kod的外键。

ALTER TABLE sira_no
    ADD CONSTRAINT METAL_KODU FOREIGN KEY(METAL_KODU)
    REFERENCES metal_kod(METAL_KODU)
    ON DELETE SET NULL
    ON UPDATE SET NULL ;

这个脚本返回:
Error Code: 1005. Can't create table 'ebs.#sql-f48_1a3' (errno: 150)

我尝试为所引用的表添加索引:
CREATE INDEX METAL_KODU_INDEX ON metal_kod (METAL_KODU);

我已经检查了字符集和排序规则,但在两个表中均无法找到解决此问题的方法。我该如何解决这个问题?
这是metal_kod表:
METAL_KODU    varchar(4)    NO    PRI
DURUM    bit(1)    NO
METAL_ISMI    varchar(30)    NO
AYAR_YOGUNLUK    smallint(6)    YES        100

你能展示一下 metal_kod 表的模式吗?在那个表中,外键应该引用哪个字段? - Manse
13个回答

283

错误代码:1005 -- 您的代码中存在错误的主键引用

通常原因是引用的外键字段不存在。可能是您有拼写错误,或者检查大小写是否一致,或者存在字段类型不匹配的情况。外键链接字段必须与定义完全匹配。

一些已知的原因可能包括:

1. 两个关键字段类型和/或大小不完全匹配。例如,如果一个是INT(10),则关键字段也需要是INT,而不是BIGINTSMALLINTTINYINT。您还应检查其中一个是否为SIGNED,而另一个是否为UNSIGNED。它们都需要完全一样。 2. 您尝试引用的关键字段之一没有索引和/或不是主键。如果关系中的某个字段不是主键,则必须为该字段创建索引。 3. 外键名称重复了已存在的键。请检查外键名称是否在数据库中唯一。仅向您的键名末尾添加几个随机字符以进行测试。 4. 你的表中有一个或两个是MyISAM表。为了使用外键,这些表都必须是InnoDB。(实际上,如果两个表都是MyISAM,则不会收到错误消息-它只是不会创建键)。在查询浏览器中,您可以指定表类型。 5. 你指定了级联ONDELETESETNULL,但相关的键字段设置为NOTNULL。您可以通过更改级联或设置字段以允许NULL值来修复此问题。 6. 确保表级别和关键列的个别字段级别的字符集和排序选项相同。 7. 在外键列上有一个默认值(即default=0) 8. 关系中的某个字段是组合(复合)键的一部分,并且没有其自己的单独索引。即使该字段作为复合键的一部分具有索引,也必须为仅该关键字段创建单独的索引才能在约束中使用它。 9. 在您的ALTER语句中存在语法错误,或者您在关系中拼写错误了其中一个字段名 10. 您的外键名称超过了64个字符的最大长度。

更多细节请参考:MySQL 错误编号 1005 无法创建表


4
问题是外键字符集不匹配。感谢您的答案。 - lamostreta
4
这个问题中提到的SHOW ENGINE INNODB STATUS 命令帮助我诊断了我的特定问题(其实是我的问题),但并没有改变原来的意思。 - Hobo
1
该死,即使它是主键,你也需要为该键创建单独的索引。谢谢,这解决了我的问题。 - RSB
3
#4 是我的问题 - 其中一个表是MyISAM,而脚本试图创建一个InnoDB表。我遇到了这个问题,当我尝试部署一个旧系统时,该系统最初运行的是MySQL 5.0或类似版本,其中默认的存储引擎是MyISAM并且脚本可以正常运行。我的当前环境是5.5,而默认的存储引擎是InnoDB。在脚本开头添加“set names 'utf8', storage_engine=MYISAM;”解决了我的问题。感谢@user319198和@Stefano为我提供详细的答案!:o) - Boris Chervenkov
1
我的代码缺少了 #1 中提到的 'unsigned' 属性,谢谢! - helvete
显示剩余8条评论

11

当你将数据库从一个服务器导出到另一个服务器时,默认情况下表会按字母顺序列出,这种情况也可能会发生。
因此,在这种情况下,你的第一个表可能具有尚未创建的另一个表的外键关系。在这种情况下,需要禁用foreign_key_checks并创建数据库。

只需将以下内容添加到你的脚本中:

SET FOREIGN_KEY_CHECKS=0;

它将会运作。


5
有时这是由于主表被删除(可能是通过禁用foreign_key_checks),但外键约束仍存在于其他表中。 在我的情况下,我已经删除了表并尝试重新创建它,但对我来说仍然出现了相同的错误。
因此,如果存在任何外键约束,请尝试从所有表中删除所有外键约束,然后更新或创建表。

4

经常出现的情况是外键和参考键的类型或长度不相同。


2

我曾经遇到过类似的错误。问题出在子表和父表的字符集和排序规则不一致。可以通过添加ENGINE = InnoDB DEFAULT CHARACTER SET = utf8;来解决这个问题。

CREATE TABLE IF NOT EXISTS `country` (`id` INT(11) NOT NULL AUTO_INCREMENT,...) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8;

在SQL语句中的“...”表示有一些缺失的代码。


2

错误代码:1005

我也遇到过类似的问题,以下是我尝试的一些方法(没有特定顺序,除了解决方案):

  1. 更改外键名称(无效)
  2. 缩短外键长度
  3. 验证数据类型(没有问题)
  4. 检查索引
  5. 检查排序规则(一切正常)
  6. 清空表格(无用)
  7. 删除并重新创建表格
  8. 检查是否存在循环引用——一切正常
  9. 最后,我发现我同时打开了两个编辑器,一个是 PhpStorm(JetBrains),另一个是 MySQL Workbench。看起来 PhpStorm / MySQL Workbench 会创建某种编辑锁。

    为了检查是否存在锁定问题(也可能是另一个问题),我关闭了 PhpStorm,这解决了我的问题。


2

外键必须与它所引用的主键具有完全相同的类型。例如,如果主键的类型为“INT UNSIGNED NOT NULL”,则外键的类型也必须是“INT UNSIGNED NOT NULL”。

CREATE TABLE employees(
id_empl INT UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id)
);
CREATE TABLE offices(
id_office INT UNSIGNED NOT NULL AUTO_INCREMENT,
id_empl INT UNSIGNED NOT NULL,
PRIMARY KEY(id),
CONSTRAINT `constraint1` FOREIGN KEY (`id_empl`) REFERENCES `employees` (`id_empl`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='my offices';

无符号是我的问题所在。谢谢! - Gabo

2

我曾经遇到过同样的错误信息。最后我发现我在命令中拼写了表名。

ALTER TABLE `users` ADD FOREIGN KEY (country_id) REFERENCES country (id);

对比

ALTER TABLE `users` ADD FOREIGN KEY (country_id) REFERENCES countries (id);

我很惊讶为什么MySQL不能判断这样的表不存在...

1

这种情况发生在我的案例中,因为在约束声明中引用的表名不正确(我忘记了表名中的大写字母):

ALTER TABLE `Window` ADD CONSTRAINT `Windows_ibfk_1` FOREIGN KEY (`WallId`) REFERENCES `Wall` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;

1

刚刚提到了MyISAM。只需尝试在语句末尾添加ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2;,假设您的其他表都是使用MyISAM创建的。

CREATE TABLE IF NOT EXISTS `tablename` (
  `key` bigint(20) NOT NULL AUTO_INCREMENT,
  FOREIGN KEY `key` (`key`) REFERENCES `othertable`(`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接