鉴于架构:
我需要的是每个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_1
FOREIGN KEY(belongs_to
)REFERENCES {{ 1}}(users
)ON DELETE NO ACTION ON UPDATE NO ACTION)
我怀疑这是由于循环依赖,但我怎么能解决它(和维护参照完整性)?
答案 0 :(得分:7)
解决此问题的唯一方法(至少使用MySQL的有限功能)在两个FK列中允许NULL
值。创建具有主要标识的新用户将看起来像这样:
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
列的解决方案
答案 1 :(得分:6)
我不会这样实现它。
从表格primary_identity
中移除字段users
,然后在名为user_profiles
的表格is_primary
中添加其他字段,并将其用作主要配置文件的指标
答案 2 :(得分:1)
这将阻止FKs
使用NULL,但仍然不强制主要配置文件存在 - 必须由应用程序管理。
请注意{UserID, ProfileID}
表上的备用键(唯一索引)Profile
,并在PrimaryProfile
上匹配FK。
答案 3 :(得分:1)
这个问题是在How to drop tables with cyclic foreign keys in MySQL从删除方面提出的,但我认为其中一个答案也适用于此:
SET foreign_key_checks = 0;
INSERT <user>
INSERT <user identity>
SET foreign_key_checks = 1;
将其作为一个事务并立即提交。我没有尝试过,但它适用于删除,所以我不知道为什么它不适用于插入。
答案 4 :(得分:0)
我没有用它,但你可以试试INSERT IGNORE。我会做其中的两个,每个表一个,这样一旦完成,参考完整性就会维持。如果您在事务中执行它们,则可以在插入第二个事件时回滚。
由于您忽略了使用此功能的约束,您应该检查程序代码,否则您可能会在数据库中找到忽略约束的数据。 < / p>
感谢@Mihai指出上述问题。另一种方法是在插入时禁用约束,然后重新启用它们。但是,在可能产生比可接受的更多开销的大型表上 - 尝试一下吗?
答案 5 :(得分:0)
问题似乎是您尝试将主要身份信息保留在user_identities表中。
相反,我建议您将主要用户信息(名称/电子邮件)放入users表中。不要使用user_identities表的外键。
只有来自user_identities表的外键
所有约束现在都可以正常工作,因为它们只是一种方式。
除非主要用户(在表用户中)存在,否则无法输入user_identities。同样,在存在子身份的情况下(在user_identities中),主要用户不应该是可删除的。
您可能希望将表的名称更改为“primary_users”和“secondary_users”,以使其显而易见。
这听起来不错吗?