当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《何时/为何在SQLServer中使用级联?》经验,为你挑选了8个好方法。

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

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

我最关注每个场景的具体例子,最好是那些成功使用它们的人.



1> Joel Coehoor..:

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

有些人根本不喜欢级联.

级联删除

当关系的语义可能涉及排他性"属于 "描述时,级联删除可能是有意义的.例如,OrderLine记录是其父订单的一部分,OrderLines永远不会在多个订单之间共享.如果订单消失,OrderLine也应如此,没有订单的行将是一个问题.

Cascade Delete的规范示例是SomeObject和SomeObjectItems,在没有相应主记录的情况下,项目记录永远不会有任何意义.

你应该使用级联删除,如果你保存历史或使用"软/逻辑删除",您只设置一个删除位列1 /真.

级联更新

当您在表中使用真实密钥而不是代理键(标识/自动增量列)时,级联更新可能有意义.

Cascade Update的典型示例是当您有可变外键时,例如可以更改的用户名.

你应该使用级联更新与被标识/自动增量列键.

级联更新最好与唯一约束一起使用.

何时使用级联

在允许级联操作之前,您可能希望从用户那里获得额外的强确认,但这取决于您的应用程序.

如果您设置了错误的外键,级联可能会让您遇到麻烦.但如果你这样做,你应该没问题.

在彻底理解之前使用级联是不明智的.但是,它是一个有用的功能,因此值得花时间去理解.


@HLGEM - 我没有看到相关性.如果级联操作导致速度减慢,则等效的手动过程将导致相同的减速或在事务需要回滚时不被正确保护.
请注意,当"所谓的"自然键看起来不是这些真正有效的唯一键时,通常也会使用级联更新.事实上,我确信只有标准化程度较低的数据库模型才需要级联更新,它们是凌乱的表格和凌乱的代码的开放门户.
为什么IDENTITY或自动增量列上是否有级联更新?我可以看出为什么它不是*必要的*因为你不需要改变那些(任意的)值,但是如果其中一个*做了*改变,至少参照完整性将是完整的.
10颗子弹?那么现在我们知道乔尔没有发射左轮手枪.

2> Vinko Vrsalo..:

外键是确保数据库参照完整性的最佳方法.避免由于神奇而导致的级联就像在汇编中编写所有内容一样,因为你不相信编译器背后的魔力.

例如,错误使用外键,例如向后创建它们是坏事.

Juan Manuel的示例是规范示例,如果您使用代码,则会有更多机会将虚假的DocumentItems留在数据库中,这会让您感到困惑.

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

@Aidan,你提到的清晰度是高成本的,在你的数据库中留下虚假数据的可能性很小.对我来说,通常只是缺乏对数据库的熟悉,并且无法在使用能够助长恐惧的数据库之前找到哪些FK.要么是,要么不断地滥用级联,在实体没有概念相关的情况下使用它,或者你必须保存历史.


@Cruachan:在我看来,这条规则很简单.如果没有父数据,数据没有那么强烈相关,那么它就不能保证级联关系.这就是我在答案的最后一句中试图解决的问题.
首先使用那种"自然"主键是一个非常糟糕的主意.
在我的职业生涯中至少有两次看到了被误解的级联删除的商业威胁后果我非常不愿意自己使用它们除了最明确的案例.在这两种情况下,数据都已被删除,因为级联实际上应该保留但不是 - 并且在正常备份周期失去了轻松恢复的可能性之前未检测到它.Vinko从纯粹的逻辑观点来看是正确的,然而在现实世界中,使用级联暴露了一个人类的错误和不可预见的后果比我想要的更多.
RE:针对艾丹的评论.不,将CASCADE留在FK上不会增加​​留下虚假数据的机会.它减少了命令影响的数据超出预期并增加代码的可能性.抛弃FK完全留下虚假数据的机会.

3> Loofer..:

我从不使用级联删除.

如果我想从数据库中删除一些东西,我想明确告诉数据库我想要取出什么.

当然它们是数据库中可用的功能,有时可以使用它们,例如,如果你有一个'order'表和'orderItem'表,你可能想删除一个项目时清除项目订购.

我喜欢在代码(或存储过程)中使用它而不是"魔术"发生的清晰度.

出于同样的原因,我也不是触发器的粉丝.

需要注意的是,如果您确实删除了"订单",即使级联删除已删除了50个"orderItem",您也会收到"1行受影响"报告.


为什么不摆脱主键呢?您可以清楚地确保代码中的唯一值.
@Vinko:删除和更新具有明确定义的默认语义.通过级联或触发器更改行为以完成更多工作会留下比预期更多的机会.不,没有测试我不工作,是的,我的数据库是记录在案的.但是在编写代码时我是否还记得每一篇文档?如果我想要更高级别的语义,比如删除父级和子级,那么我将编写并使用SP来执行此操作.
@Vinko:为什么'Gasp'SPs?SP绝对是数据库是关键企业资产的方式.在这种情况下,有一个强有力的论据是讨论限制*所有*数据访问SP,或者至少除了Select之外的所有数据访问.请参阅http://stackoverflow.com/questions/1171769/when-should-i-use-stored-procedures/1171981#1171981下的答案
@MusiGenesis,Aidan并不主张删除FK.FK仍然保护数据,但没有CASCADE ON ....意外的魔法不会发生.
@Vinko.魔术的问题不在于有能力的开发人员或DBA,5年后与Joe interen一起,当DBA度假时,他们被赋予了"简单"的维护任务,然后在没有人意识到的情况下搞砸公司数据.级联有它们的位置,但在部署它们之前考虑包括人为因素在内的全部情况非常重要.
@Cruachan:如果'interen'只是因为你使用了cascade而搞砸了生产数据,就会显示你错误地使用了级联.并且还显示您有蹩脚的备份程序.
@Vinko:我并不是真的不同意你所说的任何事情,只是这种经历教会我对级联的超级谨慎,因为如果你对他们有一些错误,那么意想不到的后果会转过来并且更难咬你.在大多数情况下,我宁愿以牺牲一些不便为代价来保护数据,而不是采用更简单但更易受攻击的方式,即使级联在一些计算机科学方面更"正确".
@Cruachan:问题在于,在数据库中实现级联的替代方法是在应用程序的代码中实现它们(或者,在喘息时,在SP中).当需求或环境发生变化时,该代码仍会在未来几年内叮咬您.所以真的没有好办法,除非你真正提倡的是完全避免删除,只是在任何地方使用软删除.在某些情况下可能有意义,但问题不在于数据库中的级联,一般是级联更改(无论它到底是什么.)软删除可能确实是这些方法...

4> Mathias F..:

我通过级联删除工作了很多.

知道对数据库起作用的人可能永远不会留下任何不需要的数据.如果依赖关系增长,我只需更改Management Studio中diagramm中的约束,我就不必调整sp或dataacces.

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



5> Martynnw..:

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

我不认为级联删除与触发器一样糟糕,因为它们只删除数据,触发器内部可能有各种令人讨厌的东西.

一般来说,我完全避免使用真正的Deletes并使用逻辑删除(即,将一个名为isDeleted的位列设置为true).


您让我好奇地学习更多。为什么您强烈喜欢逻辑删除?您正在使用的数据与它有关系吗?

6> juan..:

一个例子是当你有实体之间的依赖关系时...即:Document - > DocumentItems(当你删除Document时,DocumentItems没有理由存在)



7> testpattern..:

使用级联删除,如果删除了引用的PK记录,则需要删除带有FK的记录.换句话说,如果没有引用记录,记录就毫无意义.

我发现级联删除有用,以确保默认情况下删除死引用,而不是导致空异常.



8> Durai Amutha..:

开删除级联:

想要删除子表中的行时如果在父表中删除相应的行

如果不使用级联删除,则会导致参照完整性的错误。

在更新级联上:

当您想更改主键中的外键中的更新

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有