如何使用T-SQL临时禁用外键约束?
禁用和启用SQL Server中支持的外键约束? 或者是我唯一的select,然后重新create
约束?
如果要禁用数据库中的所有约束,只需运行以下代码:
-- disable all constraints EXEC sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
要重新打开它们,请运行:(打印是可选的,当然只是列出表格)
-- enable all constraints exec sp_MSforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
当从一个数据库向另一个数据库填充数据时,我发现它很有用。 这比删除约束要好得多。 正如你所提到的那样,在数据库中删除所有数据并重新填充数据(比如在testing环境中)时,它会很方便。
如果你删除所有的数据,你可能会发现这个解决scheme是有帮助的。
有时候也可以禁用所有的触发器,你可以在这里看到完整的解决scheme。
http://www.sqljunkies.com/WebLog/roman/archive/2005/01/30/7037.aspx
-- Disable all table constraints ALTER TABLE MyTable NOCHECK CONSTRAINT ALL -- Enable all table constraints ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT ALL -- Disable single constraint ALTER TABLE MyTable NOCHECK CONSTRAINT MyConstraint -- Enable single constraint ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT MyConstraint
你最好的select是DROP和CREATE外键约束。
在这篇文章中,我没有find可以为我工作的例子,如果外键引用不同的模式,那么就不会工作,如果外键引用多个列,那么另外一个就不行。 该脚本考虑了每个外键的多个模式和多个列。
这里是生成“ADD CONSTRAINT”语句的脚本,对于多列,它将用逗号分隔它们( 确保在执行DROP语句之前保存该输出 ):
PRINT N'-- CREATE FOREIGN KEY CONSTRAINTS --'; SET NOCOUNT ON; SELECT ' PRINT N''Creating '+ const.const_name +'...'' GO ALTER TABLE ' + const.parent_obj + ' ADD CONSTRAINT ' + const.const_name + ' FOREIGN KEY ( ' + const.parent_col_csv + ' ) REFERENCES ' + const.ref_obj + '(' + const.ref_col_csv + ') GO' FROM ( SELECT QUOTENAME(fk.NAME) AS [const_name] ,QUOTENAME(schParent.NAME) + '.' + QUOTENAME(OBJECT_name(fkc.parent_object_id)) AS [parent_obj] ,STUFF(( SELECT ',' + QUOTENAME(COL_NAME(fcP.parent_object_id, fcp.parent_column_id)) FROM sys.foreign_key_columns AS fcP WHERE fcp.constraint_object_id = fk.object_id FOR XML path('') ), 1, 1, '') AS [parent_col_csv] ,QUOTENAME(schRef.NAME) + '.' + QUOTENAME(OBJECT_NAME(fkc.referenced_object_id)) AS [ref_obj] ,STUFF(( SELECT ',' + QUOTENAME(COL_NAME(fcR.referenced_object_id, fcR.referenced_column_id)) FROM sys.foreign_key_columns AS fcR WHERE fcR.constraint_object_id = fk.object_id FOR XML path('') ), 1, 1, '') AS [ref_col_csv] FROM sys.foreign_key_columns AS fkc INNER JOIN sys.foreign_keys AS fk ON fk.object_id = fkc.constraint_object_id INNER JOIN sys.objects AS oParent ON oParent.object_id = fkc.parent_object_id INNER JOIN sys.schemas AS schParent ON schParent.schema_id = oParent.schema_id INNER JOIN sys.objects AS oRef ON oRef.object_id = fkc.referenced_object_id INNER JOIN sys.schemas AS schRef ON schRef.schema_id = oRef.schema_id GROUP BY fkc.parent_object_id ,fkc.referenced_object_id ,fk.NAME ,fk.object_id ,schParent.NAME ,schRef.NAME ) AS const ORDER BY const.const_name
这是生成“DROP CONSTRAINT”语句的脚本:
PRINT N'-- DROP FOREIGN KEY CONSTRAINTS --'; SET NOCOUNT ON; SELECT ' PRINT N''Dropping ' + fk.NAME + '...'' GO ALTER TABLE [' + sch.NAME + '].[' + OBJECT_NAME(fk.parent_object_id) + ']' + ' DROP CONSTRAINT ' + '[' + fk.NAME + '] GO' FROM sys.foreign_keys AS fk INNER JOIN sys.schemas AS sch ON sch.schema_id = fk.schema_id ORDER BY fk.NAME
要禁用约束,请使用NOCHECK对表进行ALTER更改
ALTER TABLE [TABLE_NAME] NOCHECK CONSTRAINT [ALL|CONSTRAINT_NAME]
为了使你必须使用双重检查
ALTER TABLE [TABLE_NAME] WITH CHECK CHECK CONSTRAINT [ALL|CONSTRAINT_NAME]
- 启用时请注意双重检查 。
- ALL意味着在表中的所有约束。
完成后,如果需要检查状态,请使用此脚本列出约束状态。 将是非常有益的:
SELECT (CASE WHEN OBJECTPROPERTY(CONSTID, 'CNSTISDISABLED') = 0 THEN 'ENABLED' ELSE 'DISABLED' END) AS STATUS, OBJECT_NAME(CONSTID) AS CONSTRAINT_NAME, OBJECT_NAME(FKEYID) AS TABLE_NAME, COL_NAME(FKEYID, FKEY) AS COLUMN_NAME, OBJECT_NAME(RKEYID) AS REFERENCED_TABLE_NAME, COL_NAME(RKEYID, RKEY) AS REFERENCED_COLUMN_NAME FROM SYSFOREIGNKEYS ORDER BY TABLE_NAME, CONSTRAINT_NAME,REFERENCED_TABLE_NAME, KEYNO
SQL-92标准允许将一个常量声明为DEFERRABLE,以便它可以在事务范围内被隐式地或显式地推迟。 不幸的是,SQL Server仍然缺less这种SQL-92function。
对我来说,将一个约束改为NOCHECK类似于正在改变数据库结构 – 当然还有一些需要避免的约束(例如用户需要增加的权限)。
SET NOCOUNT ON DECLARE @table TABLE( RowId INT PRIMARY KEY IDENTITY(1, 1), ForeignKeyConstraintName NVARCHAR(200), ForeignKeyConstraintTableSchema NVARCHAR(200), ForeignKeyConstraintTableName NVARCHAR(200), ForeignKeyConstraintColumnName NVARCHAR(200), PrimaryKeyConstraintName NVARCHAR(200), PrimaryKeyConstraintTableSchema NVARCHAR(200), PrimaryKeyConstraintTableName NVARCHAR(200), PrimaryKeyConstraintColumnName NVARCHAR(200), UpdateRule NVARCHAR(100), DeleteRule NVARCHAR(100) ) INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName) SELECT U.CONSTRAINT_NAME, U.TABLE_SCHEMA, U.TABLE_NAME, U.COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE U INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME WHERE C.CONSTRAINT_TYPE = 'FOREIGN KEY' UPDATE @table SET T.PrimaryKeyConstraintName = R.UNIQUE_CONSTRAINT_NAME, T.UpdateRule = R.UPDATE_RULE, T.DeleteRule = R.DELETE_RULE FROM @table T INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME UPDATE @table SET PrimaryKeyConstraintTableSchema = TABLE_SCHEMA, PrimaryKeyConstraintTableName = TABLE_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME UPDATE @table SET PrimaryKeyConstraintColumnName = COLUMN_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME --SELECT * FROM @table SELECT ' BEGIN TRANSACTION BEGIN TRY' --DROP CONSTRAINT: SELECT ' ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + '] DROP CONSTRAINT ' + ForeignKeyConstraintName + ' ' FROM @table SELECT ' END TRY BEGIN CATCH ROLLBACK TRANSACTION RAISERROR(''Operation failed.'', 16, 1) END CATCH IF(@@TRANCOUNT != 0) BEGIN COMMIT TRANSACTION RAISERROR(''Operation completed successfully.'', 10, 1) END ' --ADD CONSTRAINT: SELECT ' BEGIN TRANSACTION BEGIN TRY' SELECT ' ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + '] ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ') ON UPDATE ' + UpdateRule + ' ON DELETE ' + DeleteRule + ' ' FROM @table SELECT ' END TRY BEGIN CATCH ROLLBACK TRANSACTION RAISERROR(''Operation failed.'', 16, 1) END CATCH IF(@@TRANCOUNT != 0) BEGIN COMMIT TRANSACTION RAISERROR(''Operation completed successfully.'', 10, 1) END' GO
--Drop and Recreate Foreign Key Constraints SET NOCOUNT ON DECLARE @table TABLE( RowId INT PRIMARY KEY IDENTITY(1, 1), ForeignKeyConstraintName NVARCHAR(200), ForeignKeyConstraintTableSchema NVARCHAR(200), ForeignKeyConstraintTableName NVARCHAR(200), ForeignKeyConstraintColumnName NVARCHAR(200), PrimaryKeyConstraintName NVARCHAR(200), PrimaryKeyConstraintTableSchema NVARCHAR(200), PrimaryKeyConstraintTableName NVARCHAR(200), PrimaryKeyConstraintColumnName NVARCHAR(200) ) INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName) SELECT U.CONSTRAINT_NAME, U.TABLE_SCHEMA, U.TABLE_NAME, U.COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE U INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME WHERE C.CONSTRAINT_TYPE = 'FOREIGN KEY' UPDATE @table SET PrimaryKeyConstraintName = UNIQUE_CONSTRAINT_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME UPDATE @table SET PrimaryKeyConstraintTableSchema = TABLE_SCHEMA, PrimaryKeyConstraintTableName = TABLE_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME UPDATE @table SET PrimaryKeyConstraintColumnName = COLUMN_NAME FROM @table T INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME --SELECT * FROM @table --DROP CONSTRAINT: SELECT ' ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + '] DROP CONSTRAINT ' + ForeignKeyConstraintName + ' GO' FROM @table --ADD CONSTRAINT: SELECT ' ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + '] ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ') GO' FROM @table GO
哈姆林,我同意你的看法。 当您使用SSIS传输数据或想要复制数据时,似乎很有必要暂时禁用或删除外键约束,然后重新启用或重新创build它们。 在这些情况下,参照完整性不是问题,因为它已经在源数据库中维护。 因此,您可以放心关于此事。
第一篇文章:)
对于OP,kristof的解决scheme将起作用,除非在大删除时存在海量数据和事务日志气球问题。 而且,即使有tlog存储空间,由于删除了对tlog的写入操作,对于具有数亿行的表,操作可能花费很长时间。
我使用一系列游标来截断并重新加载我们的大型生产数据库中的大型副本。 解决schemedevise了多个模式,多个外键列,最重要的是可以在SSIS中使用。
它包括创build三个临时表(实际表)来存放DROP,CREATE和CHECK FK脚本,创build和插入这些脚本到表中,然后在表中循环并执行它们。 附加的脚本包括四部分:1)在三个登台(真实)表中创build和存储脚本; 2)通过一个光标逐个执行拖放FK脚本; 3)使用sp_MSforeachtable截断所有除了我们的三个登台表之外的数据库中的表,以及4.)执行创buildFK并在ETL SSIS包的末尾检查FK脚本。
在SSIS中的执行SQL任务中运行脚本创build部分。 在第二个执行SQL任务中运行“执行删除FK脚本”部分。 将截断脚本放入第三个Execute SQL任务中,然后在将最后的Execute SQL任务中的CREATE和CHECK脚本附加到您的控制stream末尾之前(或两个,如果需要),执行您需要执行的任何其他ETL过程。
在重新应用外键失败的情况下,将脚本存储在实际表中时,您可以从sync_CreateFK中select*,复制/粘贴到查询窗口,一次运行一个脚本,一旦修复了数据问题find那些失败/仍然不能重新申请的人。
如果失败,请不要再次重新运行脚本,否则在重新执行所有外键/检查之前,您将很可能会丢失一些创build并检查fk脚本,因为我们的登台表被删除在创build要执行的脚本之前重新创build。
---------------------------------------------------------------------------- 1) /* Author: Denmach DateCreated: 2014-04-23 Purpose: Generates SQL statements to DROP, ADD, and CHECK existing constraints for a database. Stores scripts in tables on target database for execution. Executes those stored scripts via independent cursors. DateModified: ModifiedBy Comments: This will eliminate deletes and the T-log ballooning associated with it. */ DECLARE @schema_name SYSNAME; DECLARE @table_name SYSNAME; DECLARE @constraint_name SYSNAME; DECLARE @constraint_object_id INT; DECLARE @referenced_object_name SYSNAME; DECLARE @is_disabled BIT; DECLARE @is_not_for_replication BIT; DECLARE @is_not_trusted BIT; DECLARE @delete_referential_action TINYINT; DECLARE @update_referential_action TINYINT; DECLARE @tsql NVARCHAR(4000); DECLARE @tsql2 NVARCHAR(4000); DECLARE @fkCol SYSNAME; DECLARE @pkCol SYSNAME; DECLARE @col1 BIT; DECLARE @action CHAR(6); DECLARE @referenced_schema_name SYSNAME; --------------------------------Generate scripts to drop all foreign keys in a database -------------------------------- IF OBJECT_ID('dbo.sync_dropFK') IS NOT NULL DROP TABLE sync_dropFK CREATE TABLE sync_dropFK ( ID INT IDENTITY (1,1) NOT NULL , Script NVARCHAR(4000) ) DECLARE FKcursor CURSOR FOR SELECT OBJECT_SCHEMA_NAME(parent_object_id) , OBJECT_NAME(parent_object_id) , name FROM sys.foreign_keys WITH (NOLOCK) ORDER BY 1,2; OPEN FKcursor; FETCH NEXT FROM FKcursor INTO @schema_name , @table_name , @constraint_name WHILE @@FETCH_STATUS = 0 BEGIN SET @tsql = 'ALTER TABLE ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name) + ' DROP CONSTRAINT ' + QUOTENAME(@constraint_name) + ';'; --PRINT @tsql; INSERT sync_dropFK ( Script ) VALUES ( @tsql ) FETCH NEXT FROM FKcursor INTO @schema_name , @table_name , @constraint_name ; END; CLOSE FKcursor; DEALLOCATE FKcursor; ---------------Generate scripts to create all existing foreign keys in a database -------------------------------- ---------------------------------------------------------------------------------------------------------- IF OBJECT_ID('dbo.sync_createFK') IS NOT NULL DROP TABLE sync_createFK CREATE TABLE sync_createFK ( ID INT IDENTITY (1,1) NOT NULL , Script NVARCHAR(4000) ) IF OBJECT_ID('dbo.sync_createCHECK') IS NOT NULL DROP TABLE sync_createCHECK CREATE TABLE sync_createCHECK ( ID INT IDENTITY (1,1) NOT NULL , Script NVARCHAR(4000) ) DECLARE FKcursor CURSOR FOR SELECT OBJECT_SCHEMA_NAME(parent_object_id) , OBJECT_NAME(parent_object_id) , name , OBJECT_NAME(referenced_object_id) , OBJECT_ID , is_disabled , is_not_for_replication , is_not_trusted , delete_referential_action , update_referential_action , OBJECT_SCHEMA_NAME(referenced_object_id) FROM sys.foreign_keys WITH (NOLOCK) ORDER BY 1,2; OPEN FKcursor; FETCH NEXT FROM FKcursor INTO @schema_name , @table_name , @constraint_name , @referenced_object_name , @constraint_object_id , @is_disabled , @is_not_for_replication , @is_not_trusted , @delete_referential_action , @update_referential_action , @referenced_schema_name; WHILE @@FETCH_STATUS = 0 BEGIN BEGIN SET @tsql = 'ALTER TABLE ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name) + CASE @is_not_trusted WHEN 0 THEN ' WITH CHECK ' ELSE ' WITH NOCHECK ' END + ' ADD CONSTRAINT ' + QUOTENAME(@constraint_name) + ' FOREIGN KEY ('; SET @tsql2 = ''; DECLARE ColumnCursor CURSOR FOR SELECT COL_NAME(fk.parent_object_id , fkc.parent_column_id) , COL_NAME(fk.referenced_object_id , fkc.referenced_column_id) FROM sys.foreign_keys fk WITH (NOLOCK) INNER JOIN sys.foreign_key_columns fkc WITH (NOLOCK) ON fk.[object_id] = fkc.constraint_object_id WHERE fkc.constraint_object_id = @constraint_object_id ORDER BY fkc.constraint_column_id; OPEN ColumnCursor; SET @col1 = 1; FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol; WHILE @@FETCH_STATUS = 0 BEGIN IF (@col1 = 1) SET @col1 = 0; ELSE BEGIN SET @tsql = @tsql + ','; SET @tsql2 = @tsql2 + ','; END; SET @tsql = @tsql + QUOTENAME(@fkCol); SET @tsql2 = @tsql2 + QUOTENAME(@pkCol); --PRINT '@tsql = ' + @tsql --PRINT '@tsql2 = ' + @tsql2 FETCH NEXT FROM ColumnCursor INTO @fkCol, @pkCol; --PRINT 'FK Column ' + @fkCol --PRINT 'PK Column ' + @pkCol END; CLOSE ColumnCursor; DEALLOCATE ColumnCursor; SET @tsql = @tsql + ' ) REFERENCES ' + QUOTENAME(@referenced_schema_name) + '.' + QUOTENAME(@referenced_object_name) + ' (' + @tsql2 + ')'; SET @tsql = @tsql + ' ON UPDATE ' + CASE @update_referential_action WHEN 0 THEN 'NO ACTION ' WHEN 1 THEN 'CASCADE ' WHEN 2 THEN 'SET NULL ' ELSE 'SET DEFAULT ' END + ' ON DELETE ' + CASE @delete_referential_action WHEN 0 THEN 'NO ACTION ' WHEN 1 THEN 'CASCADE ' WHEN 2 THEN 'SET NULL ' ELSE 'SET DEFAULT ' END + CASE @is_not_for_replication WHEN 1 THEN ' NOT FOR REPLICATION ' ELSE '' END + ';'; END; -- PRINT @tsql INSERT sync_createFK ( Script ) VALUES ( @tsql ) -------------------Generate CHECK CONSTRAINT scripts for a database ------------------------------ ---------------------------------------------------------------------------------------------------------- BEGIN SET @tsql = 'ALTER TABLE ' + QUOTENAME(@schema_name) + '.' + QUOTENAME(@table_name) + CASE @is_disabled WHEN 0 THEN ' CHECK ' ELSE ' NOCHECK ' END + 'CONSTRAINT ' + QUOTENAME(@constraint_name) + ';'; --PRINT @tsql; INSERT sync_createCHECK ( Script ) VALUES ( @tsql ) END; FETCH NEXT FROM FKcursor INTO @schema_name , @table_name , @constraint_name , @referenced_object_name , @constraint_object_id , @is_disabled , @is_not_for_replication , @is_not_trusted , @delete_referential_action , @update_referential_action , @referenced_schema_name; END; CLOSE FKcursor; DEALLOCATE FKcursor; --SELECT * FROM sync_DropFK --SELECT * FROM sync_CreateFK --SELECT * FROM sync_CreateCHECK --------------------------------------------------------------------------- 2.) ----------------------------------------------------------------------------------------------------------------- ----------------------------execute Drop FK Scripts -------------------------------------------------- DECLARE @scriptD NVARCHAR(4000) DECLARE DropFKCursor CURSOR FOR SELECT Script FROM sync_dropFK WITH (NOLOCK) OPEN DropFKCursor FETCH NEXT FROM DropFKCursor INTO @scriptD WHILE @@FETCH_STATUS = 0 BEGIN --PRINT @scriptD EXEC (@scriptD) FETCH NEXT FROM DropFKCursor INTO @scriptD END CLOSE DropFKCursor DEALLOCATE DropFKCursor -------------------------------------------------------------------------------- 3.) ------------------------------------------------------------------------------------------------------------------ ----------------------------Truncate all tables in the database other than our staging tables -------------------- ------------------------------------------------------------------------------------------------------------------ EXEC sp_MSforeachtable 'IF OBJECT_ID(''?'') NOT IN ( ISNULL(OBJECT_ID(''dbo.sync_createCHECK''),0), ISNULL(OBJECT_ID(''dbo.sync_createFK''),0), ISNULL(OBJECT_ID(''dbo.sync_dropFK''),0) ) BEGIN TRY TRUNCATE TABLE ? END TRY BEGIN CATCH PRINT ''Truncation failed on''+ ? +'' END CATCH;' GO ------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------- ----------------------------execute Create FK Scripts and CHECK CONSTRAINT Scripts--------------- ----------------------------tack me at the end of the ETL in a SQL task------------------------- ------------------------------------------------------------------------------------------------- DECLARE @scriptC NVARCHAR(4000) DECLARE CreateFKCursor CURSOR FOR SELECT Script FROM sync_createFK WITH (NOLOCK) OPEN CreateFKCursor FETCH NEXT FROM CreateFKCursor INTO @scriptC WHILE @@FETCH_STATUS = 0 BEGIN --PRINT @scriptC EXEC (@scriptC) FETCH NEXT FROM CreateFKCursor INTO @scriptC END CLOSE CreateFKCursor DEALLOCATE CreateFKCursor ------------------------------------------------------------------------------------------------- DECLARE @scriptCh NVARCHAR(4000) DECLARE CreateCHECKCursor CURSOR FOR SELECT Script FROM sync_createCHECK WITH (NOLOCK) OPEN CreateCHECKCursor FETCH NEXT FROM CreateCHECKCursor INTO @scriptCh WHILE @@FETCH_STATUS = 0 BEGIN --PRINT @scriptCh EXEC (@scriptCh) FETCH NEXT FROM CreateCHECKCursor INTO @scriptCh END CLOSE CreateCHECKCursor DEALLOCATE CreateCHECKCursor
find约束
SELECT * FROM sys.foreign_keys WHERE referenced_object_id = object_id('TABLE_NAME')
执行由此SQL生成的SQL
SELECT 'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) + '.[' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT ' + name FROM sys.foreign_keys WHERE referenced_object_id = object_id('TABLE_NAME')
Safeway公司。
注意:增加了用于删除约束的解决scheme,以便在没有任何约束错误的情况下删除或修改表。
WITH CHECK CHECK
几乎肯定是必需的!
一些答复和评论中提到了这一点,但我觉得重要的是再次提出这一点很重要。
使用以下命令重新启用约束(不WITH CHECK
)将会有一些严重的缺陷 。
ALTER TABLE MyTable CHECK CONSTRAINT MyConstraint;
与检查| 与NOCHECK
指定表中的数据是否针对新添加的或重新启用的FOREIGN KEY或CHECK约束进行validation。 如果未指定,则假定WITH CHECK用于新的约束,并且假定WITH NOCHECK用于重新启用的约束。
如果您不想validation现有数据的新的CHECK或FOREIGN KEY约束,请使用WITH NOCHECK。 除less数情况外,我们不build议这样做。 新的约束将在以后的所有数据更新中进行评估。 当添加约束时,由WITH NOCHECK抑制的任何约束违规可能导致将来的更新失败,如果它们更新的行数据不符合约束条件。
查询优化器不考虑使用WITH NOCHECK定义的约束。 这些约束被忽略,直到通过使用ALTER TABLE table WITH CHECK CHECK CONSTRAINT ALL重新启用它们。
注意: WITH NOCHECK是重新启用约束的默认设置。 我不得不想,为什么…
- 在执行该命令的过程中,不会评估表中现有的数据 – 成功完成并不能保证表中的数据根据约束条件有效。
- 在无效logging的下一次更新期间,约束条件将被评估,并将失败 – 导致可能与实际更新无关的错误。
- 依赖约束来确保数据有效的应用程序逻辑可能会失败。
- 查询优化器不会使用以这种方式启用的任何约束。
sys.foreign_keys系统视图提供了一些问题的可见性。 请注意,它有一个is_disabled
和一个is_not_trusted
列。 is_disabled
指示将来的数据操作操作是否将根据约束进行validation。 is_not_trusted
指示当前表中的所有数据是否已经根据约束进行了validation。
ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT MyConstraint;
你的约束是可信的吗? 找出…
SELECT * FROM sys.foreign_keys WHERE is_not_trusted = 1;
右键单击表devise并转到关系,然后在左侧窗格和右侧窗格中select外键,将实施外键约束设置为“是”(启用外键约束)或“否”(到禁用它)。
实际上,您应该能够像暂时禁用其他约束一样禁用外键约束:
Alter table MyTable nocheck constraint FK_ForeignKeyConstraintName
只要确保您禁用约束名称中列出的第一个表上的约束。 例如,如果我的外键约束是FK_LocationsEmployeesLocationIdEmployeeId,我想要使用以下内容:
Alter table Locations nocheck constraint FK_LocationsEmployeesLocationIdEmployeeId
即使违反了这个约束,也会产生一个错误,不一定会将该表作为冲突的来源。
如果你有兴趣,我有一个更有用的版本。 我从这里提取了一些代码:http: //www.dbaservices.com.au/news/drop-recreate-foreign-key-constraints/修改它以允许存储过程中的表的数组,并填充放置,截断,在执行所有的语句之前添加语句。 这使您可以控制决定哪些表需要截断。
/****** Object: UserDefinedTableType [util].[typ_objects_for_managing] Script Date: 03/04/2016 16:42:55 ******/ CREATE TYPE [util].[typ_objects_for_managing] AS TABLE( [schema] [sysname] NOT NULL, [object] [sysname] NOT NULL ) GO create procedure [util].[truncate_table_with_constraints] @objects_for_managing util.typ_objects_for_managing readonly --@schema sysname --,@table sysname as --select -- @table = 'TABLE', -- @schema = 'SCHEMA' declare @exec_table as table (ordinal int identity (1,1), statement nvarchar(4000), primary key (ordinal)); --print '/*Drop Foreign Key Statements for ['+@schema+'].['+@table+']*/' insert into @exec_table (statement) select 'ALTER TABLE ['+SCHEMA_NAME(o.schema_id)+'].['+ o.name+'] DROP CONSTRAINT ['+fk.name+']' from sys.foreign_keys fk inner join sys.objects o on fk.parent_object_id = o.object_id where exists ( select * from @objects_for_managing chk where chk.[schema] = SCHEMA_NAME(o.schema_id) and chk.[object] = o.name ) ; --o.name = @table and --SCHEMA_NAME(o.schema_id) = @schema insert into @exec_table (statement) select 'TRUNCATE TABLE ' + src.[schema] + '.' + src.[object] from @objects_for_managing src ; --print '/*Create Foreign Key Statements for ['+@schema+'].['+@table+']*/' insert into @exec_table (statement) select 'ALTER TABLE ['+SCHEMA_NAME(o.schema_id)+'].['+o.name+'] ADD CONSTRAINT ['+fk.name+'] FOREIGN KEY (['+c.name+']) REFERENCES ['+SCHEMA_NAME(refob.schema_id)+'].['+refob.name+'](['+refcol.name+'])' from sys.foreign_key_columns fkc inner join sys.foreign_keys fk on fkc.constraint_object_id = fk.object_id inner join sys.objects o on fk.parent_object_id = o.object_id inner join sys.columns c on fkc.parent_column_id = c.column_id and o.object_id = c.object_id inner join sys.objects refob on fkc.referenced_object_id = refob.object_id inner join sys.columns refcol on fkc.referenced_column_id = refcol.column_id and fkc.referenced_object_id = refcol.object_id where exists ( select * from @objects_for_managing chk where chk.[schema] = SCHEMA_NAME(o.schema_id) and chk.[object] = o.name ) ; --o.name = @table and --SCHEMA_NAME(o.schema_id) = @schema declare @looper int , @total_records int, @sql_exec nvarchar(4000) select @looper = 1, @total_records = count(*) from @exec_table; while @looper <= @total_records begin select @sql_exec = (select statement from @exec_table where ordinal =@looper) exec sp_executesql @sql_exec print @sql_exec set @looper = @looper + 1 end
标有'905'的答案看起来不错,但不起作用。
以下为我工作。 任何主键,唯一键或默认约束都无法禁用。 事实上,如果'sp_helpconstraint''在status_enabled中显示'n / a' – 意味着它不能启用/禁用。
– 生成脚本禁用
select 'ALTER TABLE ' + object_name(id) + ' NOCHECK CONSTRAINT [' + object_name(constid) + ']' from sys.sysconstraints where status & 0x4813 = 0x813 order by object_name(id)
– 将脚本生成为ENABLE
select 'ALTER TABLE ' + object_name(id) + ' CHECK CONSTRAINT [' + object_name(constid) + ']' from sys.sysconstraints where status & 0x4813 = 0x813 order by object_name(id)
一个脚本来统治他们全部:这个结合了截断和删除命令与sp_MSforeachtable,以便您可以避免丢弃和重新创build约束 – 只需指定表需要被删除而不是截断,为我的目的,我已经包括一个额外的模式filter好测量(在2008r2testing)
declare @schema nvarchar(max) = 'and Schema_Id=Schema_id(''Value'')' declare @deletiontables nvarchar(max) = '(''TableA'',''TableB'')' declare @truncateclause nvarchar(max) = @schema + ' and o.Name not in ' + + @deletiontables; declare @deleteclause nvarchar(max) = @schema + ' and o.Name in ' + @deletiontables; exec sp_MSforeachtable 'alter table ? nocheck constraint all', @whereand=@schema exec sp_MSforeachtable 'truncate table ?', @whereand=@truncateclause exec sp_MSforeachtable 'delete from ?', @whereand=@deleteclause exec sp_MSforeachtable 'alter table ? with check check constraint all', @whereand=@schema