【问题标题】:MySQL - cannot add foreign keyMySQL - 无法添加外键
【发布时间】:2013-02-26 15:06:16
【问题描述】:

我在 MySQL InnoDB 中有一个这样创建的表:

CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `type` enum('MANUAL','FACEBOOK') NOT NULL DEFAULT 'MANUAL',
  `role` enum('COOK','HOST','ALL') NOT NULL DEFAULT 'ALL',
  `about_me` varchar(1000) DEFAULT NULL,
  `food_preferences` varchar(1000) DEFAULT NULL,
  `cooking_experience` varchar(1000) DEFAULT NULL,
  `with_friend` bit(1) DEFAULT b'0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

接下来我尝试使用这样的语句添加一个表(创建表时没有添加外键,因为有问题):

CREATE TABLE `messages` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `from` bigint(20) NOT NULL,
  `to` bigint(20) NOT NULL,
  `content` varchar(10000) NOT NULL,
  `timestamp_sent` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `timestamp_read` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

创建表后,我最终需要在引用'users'.'id' 字段的'from' 和'to' 字段上添加外键:

ALTER TABLE `messages` 
  ADD CONSTRAINT `messages_users_fk`
  FOREIGN KEY (`from` , `to` )
  REFERENCES `users` (`id` , `id` )
  ON DELETE SET NULL
  ON UPDATE CASCADE
, ADD INDEX `messages_users_fk_idx` (`from` ASC, `to` ASC)

我得到的错误是:

错误:错误 1822:无法添加外键约束。引用表 'users' 中的约束 'messages_users_fk' 缺少索引。

但“用户”表在'id' 上有一个PRIMARY 索引...

还尝试采取更小的步骤并仅为'from'字段添加外键:

ALTER TABLE `messages` 
  ADD CONSTRAINT `messages_users_fk`
  FOREIGN KEY (`from` )
  REFERENCES `users` (`id` )
  ON DELETE SET NULL
  ON UPDATE CASCADE
, ADD INDEX `messages_users_fk_idx` (`from` ASC) ;

错误略有不同:

错误:错误 1825:无法在表“消息”上添加外键约束。 FOREIGN KEY 约束“cook4food/messages_users_fk”中的选项不正确。

字段的类型与其他 StackOverflow 线程中建议的问题原因相同 (bigint(20) NOT NULL)。我的表没有分区(MySQL 手册指出这是在 InnoDB 中具有外键约束的限制)。 'messages' 表当前不存储任何行,因此存储的数据不会成为任何问题。我卡住了,请帮忙。

【问题讨论】:

  • +1 很高兴看到实际的 CREATE TABLE 语句与它们一起玩 :)

标签: mysql key add


【解决方案1】:

如果您有适当的权限,您可以发出以下查询:

SHOW ENGINE innodb STATUS

...它将告诉您(以及其他一些信息)错误的确切细节:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
130311 13:30:06 Error in foreign key constraint of table test/#sql-71c_6:

  FOREIGN KEY (`from` , `to` )
  REFERENCES `users` (`id` , `id` )
  ON DELETE SET NULL
  ON UPDATE CASCADE
, ADD INDEX `messages_users_fk_idx` (`from` ASC, `to` ASC):
You have defined a SET NULL condition though some of the
columns are defined as NOT NULL.

在删除父记录时,您不能将子记录设为 NULL,因为列是 NOT NULL:

  `from` bigint(20) NOT NULL,
  `to` bigint(20) NOT NULL,

编辑:此外,我看不到单个复合键的用途。我认为您需要两个单键。

【讨论】:

  • StackOverflow 社区一如既往的有用和快速:-)。我现在可以看到我的错误了,谢谢!
  • 如果SHOW ENGINE innodb STATUS 没有显示最新的外键错误,有什么想法吗?
  • 谢谢你! +1 阿拉瓦罗。你从第二个晚上救了我!再次感谢。
  • 谢谢,@Álvaro González。我可以很快找到我的错误。
【解决方案2】:

REFERENCESusers(id,id)

您正在尝试创建无效的外键(id、id)。复合索引中涉及的列(一个涉及多于一列)不能是同一列,重复。至少我从未见过。

创建两个单独的外键,一个用于 FROM,另一个用于 TO,每个都指向用户。

【讨论】:

  • 是的,我在考虑这两种方法之间的区别。单独的外键是我真正需要的。谢谢。
【解决方案3】:

正如我们所见,

当子列from 和to 不为空时,您不能在子记录中定义 SET NULL。

因此,如果您尝试使用以下 2 条语句创建外键,您应该在 messages 表中拥有外键。

1>

ALTER TABLE `messages`  ADD CONSTRAINT `messages_users_from_fk`   FOREIGN KEY (`from` )   REFERENCES `users` (`id` )  ON DELETE CASCADE ON UPDATE CASCADE, ADD INDEX `messages_users_fk_idx` (`from` ASC) ;

和

2>

ALTER TABLE `messages`  ADD CONSTRAINT `messages_users_to_fk`   FOREIGN KEY (`to` )   REFERENCES `users` (`id` )  ON DELETE CASCADE ON UPDATE CASCADE, ADD INDEX `messages_users_fk_to_idx` (`to` ASC) ;

希望这些陈述对您有所帮助。

【讨论】:

    猜你喜欢
    • 2017-05-10
    • 2016-03-01
    • 2013-03-10
    • 2021-11-05
    • 2021-11-12
    相关资源
    最近更新 更多