(SQL Server) 如何在单个INSERT查询期间禁用外键验证?

18 浏览
0 Comments

(SQL Server) 如何在单个INSERT查询期间禁用外键验证?

目前,我正在尝试提高多行插入查询的性能,根据查询计划,目前最大的因素是针对一个大型父表的外键验证。

我知道插入查询不会插入违反外键约束的数据,因为它是一个INSERT INTO ... SELECT ... FROM查询,其中SELECT子句涉及到与父表的内连接,连接键是主键列,所以插入的行中不可能存在无效值。

我不想全局禁用外键约束。我不想在其他查询可能插入错误数据时打开窗口,并且在执行插入操作之前锁定表并禁用外键约束也没有帮助,因为在插入操作之后重新启用外键约束意味着重新验证所有行(WITH CHECK),而且两个表都很大(可能有几千万行,并且是多列自然键)。

在MSSQL中,有没有办法在单个INSERT查询的范围内禁用特定外键的验证?我真诚地希望(没有太多希望[1])我只是错过了解释该选项的文档。

[1]为什么引擎会相信用户不使用该选项执行可能插入错误数据的查询?这似乎只是对LOCK TABLE - DISABLE FK - INSERT - ENABLE FK - UNLOCK TABLE方法的一种语法糖。但是我还是要问一下……

0
0 Comments

有时这是最好的解决方案。虽然通常不是这样。但是除了在之前禁用并在之后重新启用之外,没有其他方法来执行它。

 ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

然后,在之后执行:

 ALTER TABLE foo CHECK CONSTRAINT CK_foo_column

这基本上是我所期望的。

0
0 Comments

从上述内容中,我们可以得出以下问题的原因和解决方法:

问题:如何在单个INSERT查询期间禁用外键验证?

原因:虽然可以禁用外键验证,但这是一个非常糟糕的决定。在某个时刻,您必须验证约束 - 现在付费或以后付费。而以后付费最终意味着您的假设(所有行都是有效的)将被证明是错误的。

解决方法:在单个语句或单个连接中无法禁用外键验证,这是全局的,适用于所有用户和特定表。但是,如果您确实知道该查询不会插入使外键无效的数据,则可以采取以下措施来绕过外键验证的问题。

代码:

SET FOREIGN_KEY_CHECKS = 0;
-- Your INSERT query here
SET FOREIGN_KEY_CHECKS = 1;

请注意,禁用外键验证可能会导致数据不一致和完整性问题。谨慎使用,并确保在禁用外键验证期间插入的数据是有效的,并在完成后重新启用外键验证。

0