有没有人知道一个查询列出了应用了"WITH NOCHECK"描述的数据库中的所有外键?(移除它们将提高性能和稳定性).
以下将返回当前数据库中禁用的外键名称,即WITH NOCHECK
对于SQL Server 2005/2008:
select * from sys.foreign_keys where is_disabled=1
-- drop table t1 -- drop table t2 create table t1(i int not null, fk int not null) create table t2(i int not null) -- create primary key on t2 alter table t2 add constraint pk_1 primary key (i) -- create foriegn key on t1 alter table t1 add constraint fk_1 foreign key (fk) references t2 (i) --insert some records insert t2 values(100) insert t2 values(200) insert t2 values(300) insert t2 values(400) insert t2 values(500) insert t1 values(1,100) insert t1 values(2,100) insert t1 values(3,500) insert t1 values(4,500) ---------------------------- -- 1. enabled and trusted select name,is_disabled,is_not_trusted from sys.foreign_keys GO -- 2. disable the constraint alter table t1 NOCHECK CONSTRAINT fk_1 select name,is_disabled,is_not_trusted from sys.foreign_keys GO -- 3. re-enable constraint, data isnt checked, so not trusted. -- this means the optimizer will still have to check the column alter table t1 CHECK CONSTRAINT fk_1 select name,is_disabled,is_not_trusted from sys.foreign_keys GO --4. drop the foreign key constraint & re-add -- it making sure its checked -- constraint is then enabled and trusted alter table t1 DROP CONSTRAINT fk_1 alter table t1 WITH CHECK add constraint fk_1 foreign key (fk) references t2 (i) select name,is_disabled,is_not_trusted from sys.foreign_keys GO --5. drop the foreign key constraint & add but dont check -- constraint is then enabled, but not trusted alter table t1 DROP CONSTRAINT fk_1 alter table t1 WITH NOCHECK add constraint fk_1 foreign key (fk) references t2 (i) select name,is_disabled,is_not_trusted from sys.foreign_keys GO
is_disabled
表示禁用约束
isnottrusted
表示SQL Server不信任已针对外键表检查了列.
因此,不能假设将优化重新启用外键约束.为确保优化器信任该列,最好删除外键约束并使用WITH CHECK
选项(4.)重新创建它.
SELECT * FROM sys.foreign_keys AS f Where Is_Not_Trusted = 1
以下脚本将生成alter语句,这些语句将检查现有数据并防止对当前不受信任的外键的任何新违规('with nocheck').
在SQL Server Management Studio中执行它以生成脚本,然后将它们复制到查询窗口中以执行它们.
select 'alter table ' + quotename(s.name) + '.' + quotename(t.name) + ' with check check constraint ' + fk.name +';' from sys.foreign_keys fk inner join sys.tables t on fk.parent_object_id = t.object_id inner join sys.schemas s on t.schema_id = s.schema_id where fk.is_not_trusted = 1
WITH NOCHECK只能暂时应用于FK,或者如链接文章所指出的那样对优化器无效.来自BOL:
查询优化器不考虑使用NOCHECK定义的约束.在使用ALTER TABLE表CHECK CONSTRAINT ALL重新启用这些约束之前,将忽略这些约束.
这将识别您的所有外键:(处理WITH NOCHECK位...)
SELECT C.TABLE_CATALOG [PKTABLE_QUALIFIER], C.TABLE_SCHEMA [PKTABLE_OWNER], C.TABLE_NAME [PKTABLE_NAME], KCU.COLUMN_NAME [PKCOLUMN_NAME], C2.TABLE_CATALOG [FKTABLE_QUALIFIER], C2.TABLE_SCHEMA [FKTABLE_OWNER], C2.TABLE_NAME [FKTABLE_NAME], KCU2.COLUMN_NAME [FKCOLUMN_NAME], RC.UPDATE_RULE, RC.DELETE_RULE, C.CONSTRAINT_NAME [FK_NAME], C2.CONSTRAINT_NAME [PK_NAME], CAST(7 AS SMALLINT) [DEFERRABILITY] FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS C INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU ON C.CONSTRAINT_SCHEMA = KCU.CONSTRAINT_SCHEMA AND C.CONSTRAINT_NAME = KCU.CONSTRAINT_NAME INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC ON C.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA AND C.CONSTRAINT_NAME = RC.CONSTRAINT_NAME INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C2 ON RC.UNIQUE_CONSTRAINT_SCHEMA = C2.CONSTRAINT_SCHEMA AND RC.UNIQUE_CONSTRAINT_NAME = C2.CONSTRAINT_NAME INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2 ON C2.CONSTRAINT_SCHEMA = KCU2.CONSTRAINT_SCHEMA AND C2.CONSTRAINT_NAME = KCU2.CONSTRAINT_NAME AND KCU.ORDINAL_POSITION = KCU2.ORDINAL_POSITION WHERE C.CONSTRAINT_TYPE = 'FOREIGN KEY'
参考.
另外,在SQL Server 2000和2005中,您可以使用以下命令检查是否有任何数据违反约束:
DBCC CHECKCONSTRAINTS (table_name)