18

给定架构:

在此处输入图像描述

我需要的是让每一个user_identities.belongs_to参考资料都有一个users.id.

同时,每一个users都有一个primary_identity如图所示。

但是,当我尝试添加此引用时ON DELETE NO ACTION ON UPDATE NO ACTION,MySQL 说

#1452 - 无法添加或更新子行:外键约束失败(yap. #sql-a3b_1bf, CONSTRAINT #sql-a3b_1bf_ibfk_1FOREIGN KEY ( belongs_to) REFERENCES users( id) ON DELETE NO ACTION ON UPDATE NO ACTION)

我怀疑这是由于循环依赖,但我该如何解决它(保持参照完整性)?

4

6 回答 6

11

解决这个问题的唯一方法(至少在 MySQL 的有限功能下)允许NULL两个 FK 列中的值。创建具有主要身份的新用户将如下所示:

insert into users (id, primary_identity)
values (1, null);

insert into identities (id, name, belongs_to)
values (1, 'foobar', 1);

update users 
  set primary_identity = 1
where id = 1;

commit;

此解决方案的唯一缺点是您不能强制用户具有主要身份(因为该列必须可以为空)。


另一种选择是更改为支持延迟约束的 DBMS,然后您只需插入两行,并且只会在提交时检查约束。或者使用可以有部分索引的 DBMS,然后你可以使用带有is_primary列的解决方案

于 2012-09-29T11:34:20.693 回答
7

我不会以这种方式实现它。

primary_identity从表中删除字段,并在名为users的表中添加一个附加字段,并将其用作主要配置文件的指示符user_profilesis_primary

于 2012-09-29T11:11:51.080 回答
2

这将防止 NULL 存在FKs,但仍不会强制存在主要配置文件 - 必须由应用程序管理。

{UserID, ProfileID}注意 table上的备用键(唯一索引)Profile和匹配的 FK PrimaryProfile

在此处输入图像描述

于 2012-10-04T19:49:13.120 回答
0

我没用过,但你可以试试INSERT IGNORE。我会做这两个,每个表一个,这样一旦它们都完成,参照完整性就会得到维护。如果您在事务中执行它们,如果插入第二个有问题,您可以回滚。

由于您忽略了此功能的约束,因此您应该在程序代码中进行检查,否则您的数据库中的数据可能会忽略您的约束。

感谢@Mihai 指出上述问题。另一种方法是在插入时禁用约束,然后重新启用它们。但是,在可能产生超出可接受的开销的大表上 - 试试看?

于 2012-09-29T11:28:32.690 回答
0

问题似乎是您试图将主要身份信息保留在 user_identities 表中。

相反,我建议您将主要用户信息(姓名/电子邮件)放入用户表中。不要对 user_identities 表使用外键。

仅来自 user_identities 表的外键

所有约束现在都可以正常工作,因为它们只是一种方式。

除非主用户(在表 users 中)存在,否则无法输入 user_identities。同样,如果存在现有子身份(在 user_identities 中),则不应删除主用户。

您可能希望将表的名称更改为“primary_users”和“secondary_users”,以明确发生了什么。

听起来好吗?

于 2012-10-01T09:36:37.093 回答
0

这个问题是在如何从删除方面在 MySQL 中删除带有循环外键的表时提出的,但我认为其中一个答案也适用于这里:

SET foreign_key_checks = 0;
INSERT <user>
INSERT <user identity>
SET foreign_key_checks = 1;

将其作为一个事务并一次性提交。我没有尝试过,但它适用于删除,所以我不知道为什么它不适用于插入。

于 2013-08-05T14:17:09.623 回答