什么是可以使外键变得不可信的场景

时间:2013-12-09 16:54:55

标签: sql sql-server

我有一个OLTP和一个OLAP数据库,我们在OLAP中保存了13个月的滚动数据。多个ETL作业使OLAP与夜间作业保持同步,并且在执行ETL时,没有任何作业禁用外键。偶尔,由于我尚未发现的原因,我的一些OLTP外键变得不可信。我使用下面的脚本(感谢Brent Ozar的小组)来识别并修复这些密钥。

我的问题是:除了手动禁用然后忘记重新启用密钥外,哪些情况会导致外键变得不受信任?我已经完成了我们的ETL工作,没有任何事情发生。

用于识别并修复不受信任密钥的脚本:

识别不受信任的密钥

以下脚本,Brent Ozar组的称赞,将有助于识别不受信任的密钥。请注意,必须在连接到要检查的给定数据库时运行此脚本。

SELECT '[' + s.name + '].[' + o.name + '].[' + i.name + ']' AS keyname
from sys.foreign_keys i
INNER JOIN sys.objects o ON i.parent_object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE i.is_not_trusted = 1 AND i.is_not_for_replication = 0

SELECT '[' + s.name + '].[' + o.name + '].[' + i.name + ']' AS keyname
from sys.check_constraints i
INNER JOIN sys.objects o ON i.parent_object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE i.is_not_trusted = 1 AND i.is_not_for_replication = 0 AND i.is_disabled = 0

修复不受信任的密钥

识别出不受信任的密钥后,请使用以下脚本重新启用它们:

ALTER TABLE MyTableName WITH CHECK CHECK CONSTRAINT MyConstraintName

大型表格需要一些时间,因此应在维护时段执行此操作。由于禁用了密钥,因此您可能会发现不符合约束规则的键值。需要编辑这些值或删除行以便成功重新启用密钥。

更改PriceGuide和PriceGuideDW的表脚本

我已经针对我们的数据库对Brent Ozar脚本进行了一些修改。这些脚本将生成必要的alter table脚本以修复不受信任的密钥:

Use PriceGuide
Go 
SELECT 'ALTER TABLE [' + o.name + '] WITH CHECK CHECK CONSTRAINT ' +
--'[' + s.name + '].[' + o.name + '].
+ '[' + i.name + '];' AS keyname
from sys.foreign_keys i
INNER JOIN sys.objects o ON i.parent_object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE i.is_not_trusted = 1 AND i.is_not_for_replication = 0

SELECT 'ALTER TABLE [' + o.name + '] WITH CHECK CHECK CONSTRAINT ' +
--'[' + s.name + '].[' + o.name + '].
+ '[' + i.name + '];' AS keyname
from sys.check_constraints i
INNER JOIN sys.objects o ON i.parent_object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE i.is_not_trusted = 1 AND i.is_not_for_replication = 0 AND i.is_disabled = 0

Use PriceGuideDW
Go 
SELECT 'ALTER TABLE [' + o.name + '] WITH CHECK CHECK CONSTRAINT ' +
--'[' + s.name + '].[' + o.name + '].
+ '[' + i.name + '];' AS keyname
from sys.foreign_keys i
INNER JOIN sys.objects o ON i.parent_object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE i.is_not_trusted = 1 AND i.is_not_for_replication = 0

SELECT 'ALTER TABLE [' + o.name + '] WITH CHECK CHECK CONSTRAINT ' +
--'[' + s.name + '].[' + o.name + '].
+ '[' + i.name + '];' AS keyname
from sys.check_constraints i
INNER JOIN sys.objects o ON i.parent_object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE i.is_not_trusted = 1 AND i.is_not_for_replication = 0 AND i.is_disabled = 0

2 个答案:

答案 0 :(得分:1)

好吧,添加外键WITH NOCHECK肯定是第一种想到的方式。

答案 1 :(得分:-1)

我认为您必须使用WITH CHECK CHECK CONSTRAINT才能验证现有数据是否符合约束条件。如果你回到Brent Ozar的网站,这就是他们开的处方。 http://www.brentozar.com/blitz/foreign-key-trusted/