MySQL - 无法添加外键

时间:2013-03-11 12:28:46

标签: mysql key add

我在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

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

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'的索引。

但'用户'表在PRIMARY ...

上有'id'索引

还尝试缩小步骤并为'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'表当前不存储任何行,因此存储的数据不会以任何方式出现问题。我被困了,请帮忙。

3 个答案:

答案 0 :(得分:15)

如果您拥有相应的权限,则可以发出以下查询:

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,

编辑:此外,我无法看到单个复合键的用途。我想你想要两个单键。

答案 1 :(得分:0)

REFERENCES {用户{1}} ID为( ID为,

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

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

答案 2 :(得分:0)

正如我们所见,

当子列fromto不为空时,您无法在子记录中定义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) ;

希望这些陈述可以帮助你。