【发布时间】:2020-06-19 09:19:58
【问题描述】:
背景
我有两张桌子Parent 和Child。这种关系是一对多的父 ID 与子 ID。因此,为了优化日常JOIN 查询,我正在考虑通过
ALTER TABLE Child
ADD CONSTRAINT FOREIGN KEY
parent_id
REFERENCES Parent (id);
其中Parent.id 是PRIMARY KEY。通过不显式设置ON UPDATE 或ON DELETE 子句,我相信我已经隐式设置了默认值
ON DELETE NO ACTION
ON UPDATE NO ACTION
根据MySQL 8.0 Documentation。请注意,Child.parent_id 已编入索引。
但情况是,Child 表会在Parent 表之前频繁更新,并且它有时会有关于Parent 的新数据以及从未见过的外键的Child.parent_id。这是因为Child 表是事务类记录的近乎即时的日志,是数据库的唯一输入; Parent 表是 Child 表的派生和合并摘要,任务是每隔几个小时更新一次。
现在,在阅读其他帖子时,我了解到FOREIGN KEY 要求父表的引用列是唯一的并且存在。显然我没有唯一性问题,因为我引用的父列是PRIMARY KEY,我的问题是 existence 的引用值。在一个问题中:当我将一条新记录插入到包含从未见过的Child.parent_id 的Child 表中时会发生什么?
实验
我在两个较小的表上对此进行了测试,这两个表都是在我希望优化的较大表的映像中创建的(使用 CREATE TABLE Parent LIKE... 等)。这些测试表的命名如上所述。随着这些小测试表的创建,我在测试表上定义了一个FOREIGN KEY,就像上面一样。
所以Parent 看起来像:
| id | SummaryStat1 | SummaryStat2 | ... | SummaryStatN |
|-------|--------------|--------------|-----|---------------------|
| 147 | 50.4 | 1999983 | ... | NULL |
| 99384 | 60.8 | 3592324 | ... | 2018-03-05 00:22:09 |
| ... | | | | |
还有Child 喜欢:
| id | parent_id | Stat1 | ... | StatM |
|-------------|-----------|-------|-----|---------------------|
| 1 | 147 | 18.3 | ... | 2018-02-17 14:23:10 |
| 2 | 99384 | 0.02 | ... | 2018-02-17 14:23:12 |
| (AUTO INCR) | ... | ... | ... | ... |
| 70565 | 147 | | | 2018-02-18 16:59:00 |
| ... | ... | ... | ... | ... |
因此,在设置了FOREIGN KEY 之后,我在Child 中插入了一条新记录,其中包含一个前所未见的Child.parent_id,并且数据库发出了预期的投诉:
"Cannot add or update a child row: a foreign key constraint fails..."
是否有一个众所周知的解决方法?我正在考虑修改事务流程以插入默认的Parent 记录,新的Parent.id before 数据发送到Child 表,但如果有一个简单的DB 解决方案,例如允许您存储断开连接的外键值直到父外键出现在父表中的选项。
【问题讨论】:
-
不存在
disconnected foreign key这样的东西——数据库始终施加完整性约束。您可以将child.parent_id设置为 NULL,直到创建父级。 -
但是在创建父级时如何更新
child.parent_id? -
我认为你有孩子和父母相反。
-
如果我将
child.parent_id设置为NULL,然后创建父级,将无法立即将父级连接回该子级。我只获取子信息,父信息必须源自该父信息。 -
对不起,一个更正:“...父信息必须来自子表。”
标签: mysql sql innodb mysql-8.0