How can foreign key constraints be temporarily disabled using T-SQL?
SQL Server是否支持禁用和启用外键约束?或者我唯一的选择是选择
如果你想禁用所有约束在数据库刚刚运行这个代码:
1 2 | -- disable all constraints EXEC sp_MSforeachtable"ALTER TABLE ? NOCHECK CONSTRAINT all" |
他们在转换运行:(打印,当然是可选的,它只是上市的表)
1 2 | -- enable all constraints exec sp_MSforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all" |
当我找到它有用的数据从一个到另一个populating数据库。最好的方法是多约束比下降。当你提到它是手机掉所有的数据在数据库和IT(repopulating说在测试环境)。
如果你是通过您的所有数据,你可以找到这样的解决方案是有益的。
所以有时它是一个禁用所有触发器为好的手机,你可以看到完整的解决方案在这里。
http://www.sqljunkies.com /博客/小说/档案/ 2005/01/30/7037.aspx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | -- 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 |
您的最佳的选择是删除和创建对外键约束。
我不喜欢在这工作的例子后,将"我是",也不工作,如果一个外键引用不同的工作模式,其他的人也不多,如果对外键列。考虑两个脚本,多模式和多个列,通过外资的关键。
这里是哪里,"添加脚本语句的约束",他们多做单独列由逗号(是要保存在输出之前执行拖放报表):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 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 |
这里是哪里"脚本,删除约束"语句:
1 2 3 4 5 6 7 8 9 10 11 12 | 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年龄表
1 | ALTER TABLE [TABLE_NAME] NOCHECK CONSTRAINT [ALL|CONSTRAINT_NAME] |
使你有一个使用双止回阀
1 | ALTER TABLE [TABLE_NAME] WITH CHECK CHECK CONSTRAINT [ALL|CONSTRAINT_NAME] |
- *注意在检查时检查授权。
- 所有在所有均值约束表。
一旦完成,如果你需要检查的地位,使用脚本列表中的约束状态。要非常礼貌:
1 2 3 4 5 6 7 8 9 10 11 | 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标准允许一个被约束的,这样它可以作为递延推迟(或明确implicitly在scope of a)事务。是的,仍然是一本SQL Server SQL 92的功能。
我是一个变化的约束,类似的nocheck改变数据库结构到飞掉的东西确实是约束和avoided(例如用户的需要增加的特权)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | --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 |
我也同意你,Hamlin的店。当你使用SSIS数据或传输数据时,要replicate,似乎没有必要暂时禁用或删除然后重新对外键约束或recreate启用他们。在论文的情况下,是指完整性的问题,因为它已经保持在源数据库。因此,对于这个你可以放心残余物。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | 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 |
第一篇文章:
对于OP,Kristof的解决方案将起作用,除非在大的删除上存在大量数据和事务日志气球问题。此外,即使要备用tlog存储,由于删除对tlog的写操作,对于具有数亿行的表来说,操作可能需要很长的时间。
我经常使用一系列的光标来截断和重新加载一个大型生产数据库的大型副本。解决方案为多个模式、多个外键列设计了帐户,最好是存储过程用于SSIS。
它包括创建三个临时表(实际表),以存放放置、创建和检查FK脚本,创建和插入这些脚本到表中,然后循环遍历表并执行它们。附加脚本包括四个部分:1)在三个分段(实)表中创建和存储脚本;2)通过光标逐个执行drop fk脚本;3)使用sp msforeachtable截断数据库中除三个分段表以外的所有表;4)在结束时执行create fk并检查fk脚本。您的ETL SSIS包。
在SSIS中的执行SQL任务中运行脚本创建部分。在第二个执行SQL任务中运行"execute drop fk scripts"部分。将截断脚本放入第三个执行SQL任务中,然后在控制流末尾的最后一个执行SQL任务(如果需要,可以执行两个)中附加创建和检查脚本之前,执行您需要执行的其他ETL进程。
当重新应用外键失败时,将脚本存储在实际表中已证明是非常宝贵的,因为您可以从同步创建中选择*,复制/粘贴到查询窗口中,一次运行一个,并在找到失败/仍无法重新应用的脚本后修复数据问题。
如果脚本失败,在执行之前不确保重新应用所有外键/检查,则不要重新运行该脚本,否则很可能会丢失一些创建和检查FK脚本,因为我们的临时表在创建要执行的脚本之前被删除并重新创建。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 | ---------------------------------------------------------------------------- 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 |
几乎肯定需要
这一点是在一些答案和评论中提出的,但我觉得再次提出这一点已经足够重要了。
使用以下命令(没有
1 | ALTER TABLE MyTable CHECK CONSTRAINT MyConstraint; |
WITH CHECK | WITH NOCHECK
Specifies whether the data in the table is or is not validated against
a newly added or re-enabled FOREIGN KEY or CHECK constraint. If not
specified, WITH CHECK is assumed for new constraints, and WITH NOCHECK
is assumed for re-enabled constraints.If you do not want to verify new CHECK or FOREIGN KEY constraints
against existing data, use WITH NOCHECK. We do not recommend doing
this, except in rare cases. The new constraint will be evaluated in
all later data updates. Any constraint violations that are suppressed
by WITH NOCHECK when the constraint is added may cause future updates
to fail if they update rows with data that does not comply with the
constraint.The query optimizer does not consider constraints that are defined
WITH NOCHECK. Such constraints are ignored until they are re-enabled
by using ALTER TABLE table WITH CHECK CHECK CONSTRAINT ALL.
注意:WITH NOCHECK是重新启用约束的默认设置。我想知道为什么…
sys.foreign_keys系统视图提供了对该问题的一些可见性。注意,它有一个
1 | ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT MyConstraint; |
你的约束值得信任吗?找出。。。
1 | SELECT * FROM sys.foreign_keys WHERE is_not_trusted = 1; |
找到的约束
1 2 3 | SELECT * FROM sys.foreign_keys WHERE referenced_object_id = object_id('TABLE_NAME') |
执行的SQL生成的SQL。
1 2 3 4 5 6 | 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公司。
注:增值解决方案降低的约束,这样可以把表或修改没有任何约束的错误。
右键单击表设计并转到关系,选择左侧窗格和右侧窗格中的外键,将强制外键约束设置为"是"(启用外键约束)或"否"(禁用)。
标有"905"的答案看起来不错,但不起作用。
跟随者为我工作。不能禁用任何主键、唯一键或默认约束。实际上,如果"sp_helpconstraint"显示"n/a"处于"启用"状态,则表示无法启用/禁用它。
--生成要禁用的脚本
1 2 3 | select 'ALTER TABLE ' + object_name(id) + ' NOCHECK CONSTRAINT [' + object_name(constid) + ']' from sys.sysconstraints where status & 0x4813 = 0x813 order by object_name(id) |
--生成脚本以启用
1 2 3 | select 'ALTER TABLE ' + object_name(id) + ' CHECK CONSTRAINT [' + object_name(constid) + ']' from sys.sysconstraints where status & 0x4813 = 0x813 order by object_name(id) |
实际上,您应该能够像临时禁用其他约束一样禁用外键约束:
1 | Alter table MyTable nocheck constraint FK_ForeignKeyConstraintName |
只需确保在约束名称中列出的第一个表上禁用约束。例如,如果我的外键约束是fk locationsEmployeeSlocationIdEmployeeID,我将使用以下内容:
1 | Alter table Locations nocheck constraint FK_LocationsEmployeesLocationIdEmployeeId |
即使违反此约束,也会产生一个错误,该错误不一定将该表作为冲突的源。
您可以临时禁用表上的约束,进行工作,然后重新生成它们。
这是一个简单的方法…
禁用所有索引,包括主键,这将禁用所有外键,然后仅重新启用主键,以便您可以使用它们…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | DECLARE @sql AS NVARCHAR(max)='' select @sql = @sql + 'ALTER INDEX ALL ON [' + t.[name] + '] DISABLE;'+CHAR(13) from sys.tables t where type='u' select @sql = @sql + 'ALTER INDEX ' + i.[name] + ' ON [' + t.[name] + '] REBUILD;'+CHAR(13) from sys.key_constraints i join sys.tables t on i.parent_object_id=t.object_id where i.type='PK' exec dbo.sp_executesql @sql; go |
[做一些事情,比如加载数据]
然后重新启用并重建索引…
1 2 3 4 5 6 7 8 9 | DECLARE @sql AS NVARCHAR(max)='' select @sql = @sql + 'ALTER INDEX ALL ON [' + t.[name] + '] REBUILD;'+CHAR(13) from sys.tables t where type='u' exec dbo.sp_executesql @sql; go |
如果你感兴趣的话,我有一个更有用的版本。我从一个链接不再活跃的网站上提取了一些代码。我修改了它,允许在存储过程中有一个表数组,它在执行所有语句之前填充drop、truncate和add语句。这使您可以控制哪些表需要截断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | /****** 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 |
一个脚本将它们全部规则化:这将truncate和delete命令与sp msforeachtable结合在一起,这样可以避免删除和重新创建约束-只需指定需要删除而不是截断的表,出于我的目的,我还包含了一个额外的模式过滤器,用于良好的度量(在2008r2中测试)
1 2 3 4 5 6 7 8 9 | 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 |