如何处理 mySQL 中未来孤立记录的删除

Posted

技术标签:

【中文标题】如何处理 mySQL 中未来孤立记录的删除【英文标题】:How to handle the deletion of future orphan records in mySQL 【发布时间】:2019-08-05 15:45:38 【问题描述】:

我有一个这样设计的数据库:

表格:

| Snapshot |
 * id (pk)

| Detail |
 * id (pk)
 * snapshot_id (fk_delete_cascade)
 * stat1_id (fk)
 * stat2_id (fk)
 * stat3_id (fk)
 * stat4_id (fk)

| Stats |
 * id (pk)

问题是当我删除Snapshot时,details会自动删除,因为delete cascade但相关的stats不是因为关系不好方向(细节知道统计数据,但不是相反)。这会创建大量孤立记录。

有没有一种简单的方法来处理这个我看不到的问题,或者当detail 的 4 个字段中的任何一个字段都没有使用这些孤儿 stats 时,我真的需要做一个查询来删除它们吗? ?

谢谢!

【问题讨论】:

很难在 RDBMS 中实施 1:1,n 关系。 DBMS 执行 1:0,n,因此您可以插入一个 Stats 行,而它不存在 Detail 行。反之亦然,您可以删除 Detail 行并仍然保留 Stats 行。所以不,没有什么可以为您开箱即用地处理这个问题。在 Oracle 中,我要么为此编写一个存储过程,要么创建一个复合触发器来自动删除 Stats 行。不过,我对 mysql 的了解还不够,无法在这里推荐一些最佳方法。对不起。 如果正好有 4 个统计数据,只需将它们放入 Detail。 (“不要过度规范化。”) 【参考方案1】:

确保一致性的方法是颠倒参考方向。

不要让 Detail 对 Stats 有 4 个 fk,而是在 Stats 中创建一个引用 Detail 的 fk。

Stats
* id (pk)
* detail_id (fk)

然后你可以把那个fk级联,删除一个Detail会自动删除所有相关的Stats。

但如果一个 Stat 可能被许多 Details 引用,这将不起作用。在这种情况下,您无法通过级联约束自动删除。你必须定期清理孤儿。

DELETE s FROM Stats AS s LEFT OUTER JOIN Detail AS d
  ON s.id IN (d.stat1_id, d.stat2_id, d.stat3_id, d.stat4_id)
WHERE d.id IS NULL;

不幸的是,由于 Detail 中有多个列,因此无法优化。它必须执行非常昂贵的表扫描才能尝试找到相关的详细信息行。

因此,如果您可以像我上面描述的那样反转 fk 引用,那就更好了。

【讨论】:

以上是关于如何处理 mySQL 中未来孤立记录的删除的主要内容,如果未能解决你的问题,请参考以下文章

Mysql如何处理重复数据?让你的效率更高效

如何处理重复hosts?

如何处理 SQL 代理作业错误?

如何处理Rails加入表关系删除?

MySQL 如何处理查询中的 ORDER BY 和 LIMIT?

如何处理活动流中已删除的照片