如何处理 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 中未来孤立记录的删除的主要内容,如果未能解决你的问题,请参考以下文章