打开和关闭外键约束

时间:2011-11-02 22:34:15

标签: sql-server-2008 tsql

我们有一个冗长的ETL过程,它通过一系列表格从输入文件中传输数据。

我认为不太可能在我们的表中添加关系完整性,但我不希望我们的ETL进程在遇到违规时死亡。我还希望仍然加载违反参照完整性的记录。但是,最后,我想了解所有违反参照完整性的行为。

方法1: 我可以关闭引用完整性并编写一个运行一堆存储过程的SQL过程来识别违反关系完整性的记录,但我真的很喜欢关系完整性在表本身上的想法,因为我觉得这会记录数据库中的最好的地方 - 数据库。

方法2: 我没有编写一组自定义查询来识别违规者,而是认为我们应该在流程开始时删除所有ref完整性,然后在最后添加它。在我们获得例外的地方,我们知道存在违规行为。我有点喜欢这种方法,但是不喜欢方法1,其中SQL可以编写为仅针对潜在违规者添加的记录,添加ref完整性可能会重新检查整个表 - 一个不断增长的表。当重新启用参考完整性时,数据的消费者可以确保数据是“好的”而不再执行飞行查询。我喜欢那个......

有第三种方法吗? 我看到T-SQL支持像

这样的命令
NOCHECK CONSTRAINT  
ON UPDATE  NO ACTION  
ON INSERT  NO ACTION

但我不确定它们是如何真正打算使用的。例如,

ALTER TABLE dbo.TableName     NOCHECK CONSTRAINT FK01

当您拥有可靠的来源时,这是否意图关闭constrationmt检查?我假设如果它关闭然后以这种方式打开,则设置chg仅适用于将来的操作。

您将使用哪种最佳方法来允许流程完成到最后并仍然识别所有关系完整性或可能的关系完整性违规?

2 个答案:

答案 0 :(得分:1)

1.我发现NO ACTION名称有点误导,因为这意味着如果违反约束,DML将会失败。有些RDMS,特别是mysql,有一个更好的关键字 - RESTRICT更具描述性    2.您可以使用ALTER TABLE ... NOCHECK/CHECK CONSTRAINT ALL

临时禁用/启用所有约束

答案 1 :(得分:0)

我个人永远不会关闭FK约束。这是一个滑入地狱的开始。他们是有原因的。

我会将您的ETL拆分为N行的批次,并将每个ETL包装在一个事务中。如果事务因FK违规而失败,请记录它并执行恢复要求。永远不要留下坏数据。