226

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

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

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

这可能吗?

4

5 回答 5

282
-- 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 in the database:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'

-- Re-enable constraints for all tables in the database:
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL'
---------------------------------------------------------
于 2014-10-24T16:30:45.313 回答
232

您只能在 SQL 2005+中禁用 FK 和 CHECK 约束。请参阅更改表

ALTER TABLE foo NOCHECK CONSTRAINT ALL

或者

ALTER TABLE foo NOCHECK CONSTRAINT CK_foo_column

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

于 2009-04-10T09:36:55.737 回答
56

而且,如果你想验证你没有破坏你的关系并引入孤儿,一旦你重新武装你的支票,即

ALTER TABLE foo CHECK CONSTRAINT ALL

或者

ALTER TABLE foo CHECK CONSTRAINT FK_something

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

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

那时的任何错误都将是由于未能满足约束。

于 2009-04-10T15:00:14.243 回答
16

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

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

于 2009-04-21T15:13:54.350 回答
0

禁用和启用所有外键

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 语句之后的语句中检查 @@FETCH_STATUS 的值。@@FETCH_STATUS 将反映连接上最近 FETCH 操作的状态。@@FETCH_STATUS 的有效值为:

0 = FETCH 成功
-1 = FETCH 不成功
-2 = 获取的行丢失

在循环内部,代码根据意图是禁用还是启用外键约束(使用 CHECK 或 NOCHECK 关键字)以不同方式构建 ALTER TABLE 命令。然后将该语句打印为一条消息,以便可以观察其进度,然后执行该语句。最后,当所有行都被遍历时,存储过程关闭并释放游标。

请参阅MSDN 杂志中的禁用约束和触发器

于 2009-11-12T07:56:42.860 回答