【问题标题】:How do you manage foreign key relations for newly generated keys?您如何管理新生成的键的外键关系?
【发布时间】:2020-06-19 09:19:58
【问题描述】:

背景

我有两张桌子ParentChild。这种关系是一对多的父 ID 与子 ID。因此,为了优化日常JOIN 查询,我正在考虑通过

ALTER TABLE Child
  ADD CONSTRAINT FOREIGN KEY
  parent_id
  REFERENCES Parent (id);

其中Parent.idPRIMARY KEY。通过不显式设置ON UPDATEON 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_idChild 表中时会发生什么?

实验

我在两个较小的表上对此进行了测试,这两个表都是在我希望优化的较大表的映像中创建的(使用 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


【解决方案1】:

没有“简单”的解决方案。

BEGIN;
INSERT INTO parent ...
    ON DUPLICATE KEY UPDATE
        id = LAST_INSERT_ID(id);
$parent_id = SELECT LAST_INSERT_ID();
INSERT INTO child
    ( ..., parent_id, ... )
    VALUES
    ( ..., $parent_id, ... )
COMMIT;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多