2009-12-07 614 views
25

我在表中有一行。该行在其他几个具有数百万行的表中引用了ID列。用于删除行的SQL语句总是超时。从我的设计中,我知道我希望删除的行从未在其他地方引用。因此,我希望SQL忽略必须检查所有其他表以查找该行的外键引用并立即删除该行。有没有在SQL 2008中做到这一点的快速方法? 也许沿线的东西:删除SQL行忽略所有外键和约束

DELETE FROM myTable where myTable.ID = 6850 IGNORE CONSTRAINTS 

或沿着这些线的东西。

+3

您是否考虑过在相关表格的关键参考列中添加索引?如果不存在,这将允许SQL快速确定是否有其他行引用了您尝试删除的行 - 并且可能会给您带来显着的性能提升...... – 2009-12-08 14:18:58

+0

我可以提出另一种方法。在我的系统中,大多数(数百个)表格指向dbo.Company.Id。即使删除一个没有引用的空公司,也会导致DB以十亿行检查FK完整性。解决方案:只需使用逻辑删除。 – jean 2016-07-27 16:36:24

回答

30

您可以将该表/列上的约束设置为不临时检查,然后重新启用约束。一般的形式是:

ALTER TABLE TableName NOCHECK CONSTRAINT ConstraintName 

然后重新启用所有的约束与

ALTER TABLE TableName CHECK CONSTRAINT ConstraintName 

我认为这将是暂时的,但?你显然不想一直这样做。

1

在有外键指向这一个,使用所有表:

ALTER TABLE MyOtherTable NOCHECK CONSTRAINT fk_name 
17

是的,只需运行

DELETE FROM myTable where myTable.ID = 6850 

并让发动机验证CONS训练

如果您试图成为'聪明'并禁用约束,您将付出巨大的代价:启用约束必须验证每行而不是您刚刚删除的约束。有内部标志SQL一直知道一个约束是否'可信'。您'优化'会导致将这些标志更改为'false'(意味着SQL不再信任这些约束),或者必须从头开始重新验证它们。

请参阅Guidelines for Disabling Indexes and ConstraintsNon-trusted constraints and performance

除非您做了一些固体测量结果,证明DELETE操作的约束验证是性能瓶颈,让引擎完成其工作。

+1

只是有一些实际的数字:从12M表中删除10M记录实际上是2分钟慢1个临时停用约束比它激活(12:18比10:28) - SQL-Server – Remco 2016-05-20 10:08:24

+1

在某些情况下,就像在DB重新创建一个域表一样,要求并确定禁用FK检查,因为如果你发现有人以某种方式添加了一个带有不正确代码值的查找项目,那么你必须删除该项目并用正确的代码和文本值。 – ProfK 2017-04-14 14:30:01

7

请勿在任何情况下禁用约束。这是一个非常愚蠢的做法。如果你这样做,你不能保持数据的完整性。数据完整性是数据库的首要考虑因素,因为没有它,您什么​​都没有。

正确的方法是在尝试删除父记录之前从子表中删除。您可能会超时,因为您已设置级联delte,这是大型数据库中另一个不好的做法。

+6

在某些情况下,当您确实知道自己在做什么并确保在交易结束时满足所有约束条件时,它可能非常有用。例如,SqlBulkCopy默认会忽略约束,这在您思考时很有意义。 – chris 2013-02-11 14:30:57

+1

@chris,那里的关键词真的知道你在做什么。通常这些人不会问如何禁用互联网上的限制。 – HLGEM 2013-02-11 15:02:28

1

我想从两个表中删除所有记录,因为它全部是测试数据。我使用SSMS GUI暂时禁用FK约束,然后我在两个表上运行了DELETE查询,最后我重新启用了FK约束。

要禁用FK约束:

  1. 展开数据库对象[1]
  2. 扩大相关表的对象[2]
  3. 展开 '键' 文件夹
  4. 右键点击外键
  5. 选择'修改'选项
  6. 将'强制外键约束'选项更改为'否'
  7. 关闭“外键关系”窗口
  8. 关闭表设计器选项卡
  9. 当系统提示确认保存
  10. 运行必要的修改,删除查询
  11. 重新启用外键约束你只是禁用它以同样的方式。

[1]在“对象资源管理器”窗格中,可以通过“查看”菜单选项,或按F8键来访问

[2]如果你不知道这表是一个依赖,可以通过右键单击相关表格并选择“查看依赖项”选项来进行检查。

+0

我发现删除对象资源管理器中的表更容易,并让批量重新创建它们(对于因FK约束而无法删除的表再次运行删除操作)。 – appl3r 2017-09-20 10:00:03

1

我知道这是一个旧的线程,但当我的行删除被外键约束阻止时,我在这里登陆。就我而言,我的表格设计允许在约束列中使用“NULL”值。在要删除的行中,我将受约束的列值更改为“NULL”(不违反外键约束),然后删除所有行。