何时/为什么在SQL Server中使用级联?

时间:2020-03-05 18:52:19  来源:igfitidea点击:

在SQL Server中设置外键时,在什么情况下应在删除或者更新时级联它,其背后的原因是什么?

这可能也适用于其他数据库。

我最想找的是每种情况的具体示例,最好是从成功使用它们的人那里获得的。

解决方案

回答

一个示例是当我们在实体之间具有依赖关系时,即:Document-> DocumentItems(删除Document时,DocumentItems没有理由存在)

回答

我尽量避免删除或者更新我未在SQL Server中明确请求的内容。

通过级联或者通过使用触发器。在尝试跟踪错误或者诊断性能问题时,它们往往会在一段时间内咬住我们。

我要使用它们的地方是在不花太多精力的情况下保证一致性。为了获得相同的效果,我们将必须使用存储过程。

回答

我从不使用级联删除。

如果我想从数据库中删除某些内容,我想明确地告诉数据库我要取出的内容。

当然,它们是数据库中可用的功能,有时可能可以使用它们,例如,如果我们有一个" order"表和一个" orderItem"表,则在删除某个表时可能要清除这些项。命令。

我喜欢通过在代码(或者存储过程)中进行操作而获得的清晰度,而不是发生"魔术"事件。

出于同样的原因,我也不喜欢触发器。

需要注意的是,即使我们删除了一个"订单",即使级联删除删除了50个" orderItem",我们也将得到" 1行受影响"的报告。

回答

外键是确保数据库引用完整性的最佳方法。避免由于魔术而导致的级联就像在汇编中编写所有内容一样,因为我们不相信编译器背后的魔术。

不好的是外键的错误使用,例如,向后创建外键。

胡安·曼努埃尔(Juan Manuel)的例子就是规范的例子,如果我们使用代码,则有更多的机会在数据库中留下伪造的DocumentItems来咬我们。

级联更新非常有用,例如,当我们通过可以更改的内容引用数据时,例如,用户表的主键是名称,姓氏组合。然后,我们希望该组合中的更改传播到引用的任何位置。

@Aidan,我们所指的这种清晰度付出了很高的代价,即有可能在数据库中保留虚假数据,这的确是不小的机会。对我来说,通常只是缺乏对DB的熟悉,并且在与DB合作之前无法找到哪些FK会加剧这种恐惧。或者,或者是不断地滥用级联,在实体在概念上不相关的地方,或者必须保留历史的地方使用级联。

回答

我做了很多数据库工作,很少发现级联删除有用。我曾经有效地使用过它们的一次是在报表数据库中,该数据库由每夜的工作进行更新。通过删除自上次导入以来已更改的所有顶级记录,然后重新导入已修改的记录以及与它们相关的任何内容,我可以确保正确导入任何已更改的数据。它使我不必编写从数据库底部到顶部的许多复杂删除操作。

我认为级联删除不像触发器那样糟糕,因为它们仅删除数据,触发器内部可能包含各种讨厌的东西。

通常,我完全避免使用真正的Delete方法,而是使用逻辑删除方法(例如,将名为isDeleted的位列设置为true)。

回答

到目前为止我所看到的摘要:

  • 有些人根本不喜欢级联。

级联删除

  • 当关系的语义可能涉及排他性的"是"描述的一部分时,级联删除可能很有意义。例如,OrderLine记录是其父订单的一部分,并且OrderLines将永远不会在多个订单之间共享。如果Order消失,OrderLine也应该消失,没有Order的行将成为问题。
  • 级联删除的典型示例是SomeObject和SomeObjectItems,在没有相应主记录的情况下,项目记录永远不会存在。
  • 如果要保留历史记录或者仅将已删除的位列设置为1 / true的"软/逻辑删除",则不应使用"级联删除"。

级联更新

  • 当我们在表中使用实键而不是代理键(标识/自动增量列)时,级联更新可能会很有意义。
  • 级联更新的典型示例是我们拥有可变的外键,例如可以更改的用户名。
  • 我们不应将Cascade Update与"身份/自动增量"列的键一起使用。
  • 级联更新最好与唯一约束结合使用。

何时使用级联

  • 我们可能希望在允许操作进行级联之前从用户那里得到额外的确认,但这取决于应用程序。
  • 如果我们错误地设置了外键,级联会给我们带来麻烦。但是,如果我们这样做正确的话,我们应该会没事的。
  • 在完全理解之前,使用级联是不明智的。但是,它是一个有用的功能,因此值得花一些时间来理解。

回答

我和这里的其他人一样,发现级联删除实际上仅在一定程度上有所帮助(删除其他表中的引用数据确实没有太多的工作-如果有很多表,我们只需使用脚本即可自动执行此操作),但在使用时确实很烦人有人不小心级联删除了一些难以恢复的重要数据。

我唯一使用的情况是表格表中的数据受到高度控制(例如,有限的权限),并且仅通过已验证的受控过程(例如软件更新)进行更新或者删除。

回答

我经常进行级联删除。

知道有人对数据库进行操作可能永远都不会留下任何不需要的数据,这真是一件好事。如果依赖性增加,我只需在Management Studio中更改图表中的约束即可,而不必调整sp或者dataacces。

就是说,关于级联删除和循环引用,我有1个问题。这通常会导致数据库中没有级联删除的部分。

回答

进行级联删除(而不是在代码中进行删除)的一个原因是提高性能。

情况1:使用级联删除

DELETE FROM table WHERE SomeDate < 7 years ago;

情况2:没有级联删除

FOR EACH R IN (SELECT FROM table WHERE SomeDate < 7 years ago) LOOP
   DELETE FROM ChildTable WHERE tableId = R.tableId;
   DELETE FROM table WHERE tableId = R.tableid;
   /* More child tables here */
 NEXT

其次,当我们使用级联删除添加额外的子表时,情况1中的代码将继续工作。

我只会在关系的语义是"一部分"的情况下放一个层叠。否则,当我们这样做时,某些白痴会删除数据库的一半:

DELETE FROM CURRENCY WHERE CurrencyCode = 'USD'