暂时关闭约束(MS SQL)

时间:2009-04-10 09:04:52

标签: sql sql-server sql-server-2005 constraints entity-relationship

我正在寻找一种暂时关闭所有数据库约束的方法(例如表关系)。

我需要将一个DB的表复制(使用INSERT)到另一个DB。 我知道我可以通过以正确的顺序执行命令来实现这一目标(不破坏关系)。

但如果我可以暂时关闭检查约束并在操作完成后重新打开它会更容易。

这可能吗?

5 个答案:

答案 0 :(得分:205)

您只能在SQL 2005 + 中禁用FK和CHECK约束。见ALTER TABLE

ALTER TABLE foo NOCHECK CONSTRAINT ALL

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

无法禁用主键和唯一约束,但如果我理解正确,这应该没问题。

答案 1 :(得分:190)

-- Disable the constraints on a table called tableName:
ALTER TABLE tableName NOCHECK CONSTRAINT ALL

-- Re-enable the constraints on a table called tableName:
ALTER TABLE tableName WITH CHECK CHECK CONSTRAINT ALL
---------------------------------------------------------

-- Disable constraints for all tables:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'

-- Re-enable constraints for all tables:
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'
---------------------------------------------------------

答案 2 :(得分:57)

而且,如果你想确认你没有破坏你的关系并引入孤儿,那么一旦你重新装备了支票,即

ALTER TABLE foo CHECK CONSTRAINT ALL

ALTER TABLE foo CHECK CONSTRAINT FK_something

然后您可以重新运行并对任何已检查的列执行更新,如下所示:

UPDATE myUpdatedTable SET someCol = someCol, fkCol = fkCol, etc = etc

此时的任何错误都将归因于未能满足约束条件。

答案 3 :(得分:16)

您实际上可以在单个SQL命令中禁用所有数据库约束,并重新启用它们调用另一个单个命令。参见:

我目前正在使用SQL Server 2005,但我几乎可以肯定这种方法也适用于SQL 2000

答案 4 :(得分:2)

禁用和启用所有外键

CREATE PROCEDURE pr_Disable_Triggers_v2
    @disable BIT = 1
AS
    DECLARE @sql VARCHAR(500)
        ,   @tableName VARCHAR(128)
        ,   @tableSchema VARCHAR(128)

    -- List of all tables
    DECLARE triggerCursor CURSOR FOR
        SELECT  t.TABLE_NAME AS TableName
            ,   t.TABLE_SCHEMA AS TableSchema
        FROM    INFORMATION_SCHEMA.TABLES t
        ORDER BY t.TABLE_NAME, t.TABLE_SCHEMA

    OPEN    triggerCursor
    FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema
    WHILE ( @@FETCH_STATUS = 0 )
    BEGIN

        SET @sql = 'ALTER TABLE ' + @tableSchema + '.[' + @tableName + '] '
        IF @disable = 1
            SET @sql = @sql + ' DISABLE TRIGGER ALL'
        ELSE
            SET @sql = @sql + ' ENABLE TRIGGER ALL'

        PRINT 'Executing Statement - ' + @sql
        EXECUTE ( @sql )

        FETCH NEXT FROM triggerCursor INTO @tableName, @tableSchema

    END

    CLOSE triggerCursor
    DEALLOCATE triggerCursor
  

首先,将foreignKeyCursor游标声明为SELECT语句   收集外键列表及其表名。接下来,   游标打开并执行初始FETCH语句。这个   FETCH语句将第一行的数据读入本地   变量@foreignKeyName和@tableName。循环时   游标,你可以检查@@ FETCH_STATUS的值为0,其中   表示获取成功。这意味着循环将   继续前进,以便它可以获得每个连续的外键   从行集。 @@ FETCH_STATUS可用于所有游标   连接。因此,如果您循环遍历多个游标,那就是   在语句中检查@@ FETCH_STATUS的值很重要   紧跟FETCH声明之后。 @@ FETCH_STATUS将反映出来   连接上最近的FETCH操作的状态。   @@ FETCH_STATUS的有效值为:

     

0 = FETCH成功了   -1 = FETCH不成功
  -2 =缺少提取的行

     

在循环内部,代码以不同方式构建ALTER TABLE命令   取决于意图是禁用还是启用外来   键约束(使用CHECK或NOCHECK关键字)。声明是   然后打印成一条消息,以便可以观察其进度然后再进行   声明被执行。最后,当所有行都被迭代时   通过,存储过程关闭并释放光标。

请参阅Disabling Constraints and Triggers from MSDN Magazine