下面是一些代碼,我寫來幫助我們確定並在數據庫中正確不可信的約束。它生成代碼來解決每個問題。
;WITH Untrusted (ConstraintType, ConstraintName, ConstraintTable, ParentTable, IsDisabled, IsNotForReplication, IsNotTrusted, RowIndex) AS
(
SELECT
'Untrusted FOREIGN KEY' AS FKType
, fk.name AS FKName
, OBJECT_NAME(fk.parent_object_id) AS FKTableName
, OBJECT_NAME(fk.referenced_object_id) AS PKTableName
, fk.is_disabled
, fk.is_not_for_replication
, fk.is_not_trusted
, ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(fk.parent_object_id), OBJECT_NAME(fk.referenced_object_id), fk.name) AS RowIndex
FROM
sys.foreign_keys fk
WHERE
is_ms_shipped = 0
AND fk.is_not_trusted = 1
UNION ALL
SELECT
'Untrusted CHECK' AS KType
, cc.name AS CKName
, OBJECT_NAME(cc.parent_object_id) AS CKTableName
, NULL AS ParentTable
, cc.is_disabled
, cc.is_not_for_replication
, cc.is_not_trusted
, ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(cc.parent_object_id), cc.name) AS RowIndex
FROM
sys.check_constraints cc
WHERE
cc.is_ms_shipped = 0
AND cc.is_not_trusted = 1
)
SELECT
u.ConstraintType
, u.ConstraintName
, u.ConstraintTable
, u.ParentTable
, u.IsDisabled
, u.IsNotForReplication
, u.IsNotTrusted
, u.RowIndex
, 'RAISERROR(''Now CHECKing {%i of %i)--> %s ON TABLE %s'', 0, 1'
+ ', ' + CAST(u.RowIndex AS VARCHAR(64))
+ ', ' + CAST(x.CommandCount AS VARCHAR(64))
+ ', ' + '''' + QUOTENAME(u.ConstraintName) + ''''
+ ', ' + '''' + QUOTENAME(u.ConstraintTable) + ''''
+ ') WITH NOWAIT;'
+ 'ALTER TABLE ' + QUOTENAME(u.ConstraintTable) + ' WITH CHECK CHECK CONSTRAINT ' + QUOTENAME(u.ConstraintName) + ';' AS FIX_SQL
FROM Untrusted u
CROSS APPLY (SELECT COUNT(*) AS CommandCount FROM Untrusted WHERE ConstraintType = u.ConstraintType) x
ORDER BY ConstraintType, ConstraintTable, ParentTable;
它看起來不像WITH CHECK實際上是默認值,它只是新數據的默認值。從http://msdn.microsoft.com/en-us/library/ms190273.aspx:「如果未指定,則假定WITH CHECK用於新的約束,並且假定WITH NOCHECK用於重新啓用的約束。」 – 2013-12-31 21:00:23
@ ZainRizvi:不是新數據,新約束。如果您通過`ALTER TABLE foo NOCHECK CONSTRAINT fk_b`禁用約束,然後使用`ALTER TABLE foo CHECK CONSTRAINT fk_b`重新啓用它,則不驗證約束。 `ALTER TABLE foo WITH CHECK CHECK CONSTRAINT fk_b`對於驗證數據是必要的。 – jmoreno 2015-03-14 01:16:05
我最初並不清楚這一點。第二條(冗餘)行是打開約束的函數。由於約束默認開啓,所以第二行是多餘的。 – blindguy 2016-02-26 21:20:37