首页 文章

如何使用T-SQL临时禁用外键约束?

提问于
浏览
761

是否禁用和启用SQL Server支持的外键约束?或者是我唯一的选择 drop 然后 re-create 约束?

16 回答

  • 9

    如果要禁用数据库中的所有约束,只需运行以下代码:

    -- 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"
    

    我发现在将数据从一个数据库填充到另一个数据库时很有用 . 这比删除约束要好得多 . 正如您所提到的,在将所有数据放入数据库并重新填充数据库时(例如在测试环境中),它非常方便 .

    如果您要删除所有数据,您可能会发现this solution有帮助 .

    有时也可以方便地禁用所有触发器,您可以看到完整的解决方案here .

  • 1047

    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
    
  • 9

    您最好的选择是DROP和CREATE外键约束 .

    我没有在这篇文章中找到可以“按原样”为我工作的例子,如果外键引用不同的模式,则无法工作,如果外键引用多个列,则另一个不起作用 . 此脚本同时考虑每个外键的多个模式和多个列 .

    这是生成"ADD CONSTRAINT"语句的脚本,对于多个列,它将用逗号分隔它们( be sure to save this output before executing DROP statements ):

    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
    
  • 25

    要禁用约束,您可以使用NOCHECK更改表格

    ALTER TABLE [TABLE_NAME] NOCHECK CONSTRAINT [ALL|CONSTRAINT_NAME]
    

    要使你必须使用双CHECK

    ALTER TABLE [TABLE_NAME] WITH CHECK CHECK CONSTRAINT [ALL|CONSTRAINT_NAME]
    
    • 启用时注意双 CHECK CHECK .

    • 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
    
  • 363

    SQL-92标准允许将constaint声明为DEFERRABLE,以便可以在事务范围内延迟(隐式或显式) . 遗憾的是,SQL Server仍然缺少这种SQL-92功能 .

    对我来说,将约束更改为NOCHECK类似于在飞行中更改数据库结构 - 确实是 - 并且需要避免的事情(例如用户需要增加的权限) .

  • 9
    --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传输数据或想要复制数据时,似乎必须暂时禁用或删除外键约束,然后重新启用或重新创建它们 . 在这些情况下,引用完整性不是问题,因为它已在源数据库中维护 . 因此,您可以放心这件事 .

  • 5
    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
    
  • 0

    第一篇文章:)

    对于OP,kristof的解决方案将起作用,除非在大删除上存在大量数据和事务日志气球问题 . 此外,即使使用tlog存储,由于删除写入tlog,对于具有数亿行的表,操作可能需要很长时间 .

    我使用一系列游标来频繁截断和重新加载我们庞大的 生产环境 数据库的大型副本 . 该解决方案设计了多个模式,多个外键列,最重要的是可以在SSIS中使用 .

    它涉及创建三个临时表(实际表)以容纳DROP,CREATE和CHECK FK脚本,创建这些脚本并将其插入表中,然后循环遍历表并执行它们 . 附加的脚本分为四个部分:1 . )在三个临时(真实)表中创建和存储脚本,2 . 通过游标逐个执行drop FK脚本,3 . )使用sp_MSforeachtable截断所有除了我们的三个临时表之外的数据库中的表和4.)执行create FK并检查ETL SSIS包末尾的FK脚本 .

    在SSIS中的“执行SQL”任务中运行脚本创建部分 . 在第二个执行SQL任务中运行“execute Drop FK Scripts”部分 . 将截断脚本放在第三个执行SQL任务中,然后在控制流结束时将CREATE和CHECK脚本附加到最终的执行SQL任务(或两个,如果需要)之前,执行您需要执行的任何其他ETL过程 .

    当重新应用外键失败时,实际表中脚本的存储已被证明是非常宝贵的,因为您可以从sync_CreateFK中选择*,复制/粘贴到查询窗口,一次运行一个,并在您修复数据问题后找到失败/仍然无法重新申请的人 .

    如果失败而没有确保在执行此操作之前重新应用所有外键/检查,请不要再次重新运行脚本,否则您很可能会丢失一些创建并检查fk脚本,因为我们的登台表已被删除在创建要执行的脚本之前重新创建 .

    ----------------------------------------------------------------------------
    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
    
  • 0

    WITH CHECK CHECK is almost certainly required!

    在一些答案和评论中提出了这一点,但我觉得打电话很重要它再次出来 .

    使用以下命令重新启用约束(无 WITH CHECK )将具有一些serious drawbacks .

    ALTER TABLE MyTable CHECK CONSTRAINT MyConstraint;
    

    带检查| WITH NOCHECK指定是否针对新添加或重新启用的FOREIGN KEY或CHECK约束验证表中的数据 . 如果未指定,则对新约束假定为WITH CHECK,对于重新启用的约束,假定为WITH NOCHECK . 如果您不想针对现有数据验证新的CHECK或FOREIGN KEY约束,请使用WITH NOCHECK . 除极少数情况外,我们不建议这样做 . 将在所有后续数据更新中评估新约束 . 添加约束时由WITH NOCHECK抑制的任何约束违规可能会导致将来更新失败,如果他们使用不符合约束的数据更新行 . 查询优化器不考虑使用NOCHECK定义的约束 . 在使用ALTER TABLE表WITH CHECK CHECK CONSTRAINT ALL重新启用这些约束之前,将忽略这些约束 .

    Note: WITH NOCHECK是重新启用约束的默认值 . 我不知道为什么......

    • 在执行此命令期间,不会评估表中的现有数据 - 成功完成并不能保证表中的数据根据约束有效 .

    • 在下次更新无效记录期间,将评估约束并将失败 - 导致可能与实际更新无关的错误 .

    • 依赖约束来确保数据有效的应用程序逻辑可能会失败 .

    • 查询优化器不会使用以这种方式启用的任何约束 .

    sys.foreign_keys系统视图提供了对该问题的一些可见性 . 请注意,它同时具有 is_disabledis_not_trusted 列 . is_disabled 表示是否将根据约束验证未来的数据操作操作 . is_not_trusted 指示是否已根据约束验证表中当前的所有数据 .

    ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT MyConstraint;
    

    您的约束是否值得信任?找出...

    SELECT * FROM sys.foreign_keys WHERE is_not_trusted = 1;
    
  • 0

    找到约束

    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公司 .

    Note: Added solution for droping the constraint so that table can be dropped or modified without any constraint error.

  • 1

    右键单击表设计并转到“关系”并在左侧窗格和右侧窗格中选择外键,将“强制外键约束”设置为'Yes'(以启用外键约束)或'No'(禁用它) .
    enter image description here

  • 24

    您实际上应该能够以暂时禁用其他约束的方式禁用外键约束:

    Alter table MyTable nocheck constraint FK_ForeignKeyConstraintName
    

    只需确保禁用约束名称中列出的第一个表上的约束 . 例如,如果我的外键约束是FK_LocationsEmployeesLocationIdEmployeeId,我想使用以下内容:

    Alter table Locations nocheck constraint FK_LocationsEmployeesLocationIdEmployeeId
    

    即使违反此约束也会产生错误,该错误不一定表明该表是冲突的来源 .

  • 7

    如果你有兴趣,我有一个更有用的版本 . 我从这里提取了一些代码http://www.dbaservices.com.au/news/drop-recreate-foreign-key-constraints/修改它以允许一个表数组进入存储过程,并在执行所有这些之前填充drop,truncate,add语句 . 这使您可以控制决定哪些表需要截断 .

    /****** 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
    
  • 0

    标有'905'的答案看起来不错,但不起作用 .

    以下为我工作 . 禁用任何主键,唯一键或默认约束 CAN NOT . 事实上,如果'sp_helpconstraint ' ' shows ' n / a'在status_enabled中 - 意味着它可以 NOT 被启用/禁用 .

    • 生成DISABLE脚本
    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)
    
  • 1

    一个脚本来统治它们:这将truncate和delete命令与sp_MSforeachtable相结合,这样你就可以避免删除和重新创建约束 - 只需指定需要删除而不是截断的表,为了我的目的,我已经包含了一个额外的模式过滤器措施(在2008r2测试)

    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
    
  • 6

    您可以暂时禁用表的约束,执行工作,然后重建它们 .

    这是一个简单的方法...

    禁用所有索引,包括主键,这将禁用所有外键,然后重新启用主键,以便您可以使用它们...

    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
    

    [做一些事情,比如加载数据]

    然后重新启用并重建索引......

    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
    

相关问题