首页 文章

无法截断表,因为它是由FOREIGN KEY约束引用的?

提问于
浏览
369

使用MSSQL2005,如果我先截断子表(具有FK关系主键的表),是否可以截断具有外键约束的表?

我知道我也可以

  • 使用没有where子句的 DELETE 然后使用 RESEED 身份(或)

  • 删除FK,截断表,然后重新创建FK .

我认为只要我在父母之前截断子表,我就可以不用上面的任何一个选项,但是我收到了这个错误:

无法截断表'TableName',因为它正由FOREIGN KEY约束引用 .

25 回答

  • 11

    好吧,因为我没有找到我使用的 very simple 解决方案的例子,这是:

    • 删掉外键;

    • 截断表

    • 重新创建外键

    在这里:

    1)找到导致失败的外键名称(例如:FK_PROBLEM_REASON,字段 ID ,来自表 TABLE_OWNING_CONSTRAINT )2)从表中删除该键:

    ALTER TABLE TABLE_OWNING_CONSTRAINT DROP CONSTRAINT FK_PROBLEM_REASON
    

    3)截断通缉表

    TRUNCATE TABLE TABLE_TO_TRUNCATE
    

    4)将密钥重新添加到第一个表:

    ALTER TABLE TABLE_OWNING_CONSTRAINT ADD CONSTRAINT FK_PROBLEM_REASON FOREIGN KEY(ID) REFERENCES TABLE_TO_TRUNCATE (ID)
    

    而已 .

  • 165

    如果我理解正确,您要做的是为涉及集成测试的DB设置一个干净的环境 .

    我的方法是删除整个模式并在以后重新创建它 .

    理由:

    • 您可能已经有了一个"create schema"脚本 . 重新使用它进行测试隔离很容易 .

    • 创建架构非常快 .

    • 使用这种方法,设置脚本以使每个夹具创建一个新模式(具有临时名称)非常容易,然后您可以开始并行运行测试夹具,使测试套件中最慢的部分更多快点 .

  • 317

    正确;你不能截断一个有FK约束的表 .

    通常我的过程是:

    • 删除约束

    • 截断表格

    • 重新创建约束 .

    (当然,所有这些都在交易中 . )

    当然,这仅适用于孩子已被截断的情况 . 否则我会走另一条路,完全取决于我的数据 . (要进入此处的变量太多 . )

    原始海报确定了为什么会这样;有关详细信息,请参阅this answer .

  • 2
    DELETE FROM TABLENAME
    DBCC CHECKIDENT ('DATABASENAME.dbo.TABLENAME',RESEED, 0)
    

    请注意,如果您有数百万条记录,这可能不是您想要的,因为它非常慢 .

  • -6

    因为 TRUNCATE TABLEDDL command,所以无法检查表中的记录是否被子表中的记录引用 .

    这就是为什么 DELETE 工作而 TRUNCATE TABLE 没有被另一条记录引用的原因 .

  • -3

    没有 ALTER TABLE

    -- Delete all records
    DELETE FROM [TableName]
    -- Set current ID to "1"
    -- If table already contains data, use "0"
    -- If table is empty and never insert data, use "1"
    -- Use SP https://github.com/reduardo7/TableTruncate
    DBCC CHECKIDENT ([TableName], RESEED, [0|1])
    

    作为存储过程

    https://github.com/reduardo7/TableTruncate

    Note 如果你有数百万条记录,这不是't probably what you' d,因为它非常慢 .

  • 1

    上面提供的解决方案@denver_citizen对我不起作用,但我喜欢它的精神所以我修改了一些东西:

    • 使其成为存储过程

    • 更改了填充和重新创建外键的方式

    • 原始脚本截断所有引用的表,当引用的表具有其他外键引用时,这可能导致外键冲突错误 . 此脚本仅截断指定为参数的表 . 由用户决定以正确的顺序在所有表上多次调用此存储过程

    为了公众的利益,这里有更新的脚本:

    CREATE PROCEDURE [dbo].[truncate_non_empty_table]
    
      @TableToTruncate                 VARCHAR(64)
    
    AS 
    
    BEGIN
    
    SET NOCOUNT ON
    
    -- GLOBAL VARIABLES
    DECLARE @i int
    DECLARE @Debug bit
    DECLARE @Recycle bit
    DECLARE @Verbose bit
    DECLARE @TableName varchar(80)
    DECLARE @ColumnName varchar(80)
    DECLARE @ReferencedTableName varchar(80)
    DECLARE @ReferencedColumnName varchar(80)
    DECLARE @ConstraintName varchar(250)
    
    DECLARE @CreateStatement varchar(max)
    DECLARE @DropStatement varchar(max)   
    DECLARE @TruncateStatement varchar(max)
    DECLARE @CreateStatementTemp varchar(max)
    DECLARE @DropStatementTemp varchar(max)
    DECLARE @TruncateStatementTemp varchar(max)
    DECLARE @Statement varchar(max)
    
            -- 1 = Will not execute statements 
     SET @Debug = 0
            -- 0 = Will not create or truncate storage table
            -- 1 = Will create or truncate storage table
     SET @Recycle = 0
            -- 1 = Will print a message on every step
     set @Verbose = 1
    
     SET @i = 1
        SET @CreateStatement = 'ALTER TABLE [dbo].[<tablename>]  WITH NOCHECK ADD  CONSTRAINT [<constraintname>] FOREIGN KEY([<column>]) REFERENCES [dbo].[<reftable>] ([<refcolumn>])'
        SET @DropStatement = 'ALTER TABLE [dbo].[<tablename>] DROP CONSTRAINT [<constraintname>]'
        SET @TruncateStatement = 'TRUNCATE TABLE [<tablename>]'
    
    -- Drop Temporary tables
    
    IF OBJECT_ID('tempdb..#FKs') IS NOT NULL
        DROP TABLE #FKs
    
    -- GET FKs
    SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(parent_object_id), clm1.name) as ID,
           OBJECT_NAME(constraint_object_id) as ConstraintName,
           OBJECT_NAME(parent_object_id) as TableName,
           clm1.name as ColumnName, 
           OBJECT_NAME(referenced_object_id) as ReferencedTableName,
           clm2.name as ReferencedColumnName
      INTO #FKs
      FROM sys.foreign_key_columns fk
           JOIN sys.columns clm1 
             ON fk.parent_column_id = clm1.column_id 
                AND fk.parent_object_id = clm1.object_id
           JOIN sys.columns clm2
             ON fk.referenced_column_id = clm2.column_id 
                AND fk.referenced_object_id= clm2.object_id
     --WHERE OBJECT_NAME(parent_object_id) not in ('//tables that you do not wont to be truncated')
     WHERE OBJECT_NAME(referenced_object_id) = @TableToTruncate
     ORDER BY OBJECT_NAME(parent_object_id)
    
    
    -- Prepare Storage Table
    IF Not EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Internal_FK_Definition_Storage')
       BEGIN
            IF @Verbose = 1
         PRINT '1. Creating Process Specific Tables...'
    
      -- CREATE STORAGE TABLE IF IT DOES NOT EXISTS
      CREATE TABLE [Internal_FK_Definition_Storage] 
      (
       ID int not null identity(1,1) primary key,
       FK_Name varchar(250) not null,
       FK_CreationStatement varchar(max) not null,
       FK_DestructionStatement varchar(max) not null,
       Table_TruncationStatement varchar(max) not null
      ) 
       END 
    ELSE
       BEGIN
            IF @Recycle = 0
                BEGIN
                    IF @Verbose = 1
           PRINT '1. Truncating Process Specific Tables...'
    
        -- TRUNCATE TABLE IF IT ALREADY EXISTS
        TRUNCATE TABLE [Internal_FK_Definition_Storage]    
          END
          ELSE
             PRINT '1. Process specific table will be recycled from previous execution...'
       END
    
    
    IF @Recycle = 0
       BEGIN
    
      IF @Verbose = 1
         PRINT '2. Backing up Foreign Key Definitions...'
    
      -- Fetch and persist FKs             
      WHILE (@i <= (SELECT MAX(ID) FROM #FKs))
       BEGIN
        SET @ConstraintName = (SELECT ConstraintName FROM #FKs WHERE ID = @i)
        SET @TableName = (SELECT TableName FROM #FKs WHERE ID = @i)
        SET @ColumnName = (SELECT ColumnName FROM #FKs WHERE ID = @i)
        SET @ReferencedTableName = (SELECT ReferencedTableName FROM #FKs WHERE ID = @i)
        SET @ReferencedColumnName = (SELECT ReferencedColumnName FROM #FKs WHERE ID = @i)
    
        SET @DropStatementTemp = REPLACE(REPLACE(@DropStatement,'<tablename>',@TableName),'<constraintname>',@ConstraintName)
        SET @CreateStatementTemp = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@CreateStatement,'<tablename>',@TableName),'<column>',@ColumnName),'<constraintname>',@ConstraintName),'<reftable>',@ReferencedTableName),'<refcolumn>',@ReferencedColumnName)
        SET @TruncateStatementTemp = REPLACE(@TruncateStatement,'<tablename>',@TableName) 
    
        INSERT INTO [Internal_FK_Definition_Storage]
                            SELECT @ConstraintName, @CreateStatementTemp, @DropStatementTemp, @TruncateStatementTemp
    
        SET @i = @i + 1
    
        IF @Verbose = 1
           PRINT '  > Backing up [' + @ConstraintName + '] from [' + @TableName + ']'
    
        END   
        END   
        ELSE 
           PRINT '2. Backup up was recycled from previous execution...'
    
           IF @Verbose = 1
         PRINT '3. Dropping Foreign Keys...'
    
        -- DROP FOREING KEYS
        SET @i = 1
        WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
              BEGIN
                 SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
        SET @Statement = (SELECT FK_DestructionStatement FROM [Internal_FK_Definition_Storage] WITH (NOLOCK) WHERE ID = @i)
    
        IF @Debug = 1 
           PRINT @Statement
        ELSE
           EXEC(@Statement)
    
        SET @i = @i + 1
    
    
        IF @Verbose = 1
           PRINT '  > Dropping [' + @ConstraintName + ']'
    
                 END     
    
    
        IF @Verbose = 1
           PRINT '4. Truncating Tables...'
    
        -- TRUNCATE TABLES
    -- SzP: commented out as the tables to be truncated might also contain tables that has foreign keys
    -- to resolve this the stored procedure should be called recursively, but I dont have the time to do it...          
     /*
        SET @i = 1
        WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
              BEGIN
    
        SET @Statement = (SELECT Table_TruncationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    
        IF @Debug = 1 
           PRINT @Statement
        ELSE
           EXEC(@Statement)
    
        SET @i = @i + 1
    
        IF @Verbose = 1
           PRINT '  > ' + @Statement
              END
    */          
    
    
        IF @Verbose = 1
           PRINT '  > TRUNCATE TABLE [' + @TableToTruncate + ']'
    
        IF @Debug = 1 
            PRINT 'TRUNCATE TABLE [' + @TableToTruncate + ']'
        ELSE
            EXEC('TRUNCATE TABLE [' + @TableToTruncate + ']')
    
    
        IF @Verbose = 1
           PRINT '5. Re-creating Foreign Keys...'
    
        -- CREATE FOREING KEYS
        SET @i = 1
        WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
              BEGIN
                 SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
        SET @Statement = (SELECT FK_CreationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    
        IF @Debug = 1 
           PRINT @Statement
        ELSE
           EXEC(@Statement)
    
        SET @i = @i + 1
    
    
        IF @Verbose = 1
           PRINT '  > Re-creating [' + @ConstraintName + ']'
    
              END
    
        IF @Verbose = 1
           PRINT '6. Process Completed'
    
    
    END
    
  • 9

    使用delete语句删除该表中的所有行后,使用以下命令

    delete from tablename
    
    DBCC CHECKIDENT ('tablename', RESEED, 0)
    

    编辑:更正了SQL Server的语法

  • 1

    您可以按照此步骤操作,通过 reseeding table 可以删除表格的数据 .

    delete from table_name
    dbcc checkident('table_name',reseed,0)
    

    如果出现一些错误,则必须重新设置主表 .

  • 1

    这是我编写的脚本,用于自动化该过程 . 我希望它有所帮助 .

    SET NOCOUNT ON
    
    -- GLOBAL VARIABLES
    DECLARE @i int
    DECLARE @Debug bit
    DECLARE @Recycle bit
    DECLARE @Verbose bit
    DECLARE @TableName varchar(80)
    DECLARE @ColumnName varchar(80)
    DECLARE @ReferencedTableName varchar(80)
    DECLARE @ReferencedColumnName varchar(80)
    DECLARE @ConstraintName varchar(250)
    
    DECLARE @CreateStatement varchar(max)
    DECLARE @DropStatement varchar(max)   
    DECLARE @TruncateStatement varchar(max)
    DECLARE @CreateStatementTemp varchar(max)
    DECLARE @DropStatementTemp varchar(max)
    DECLARE @TruncateStatementTemp varchar(max)
    DECLARE @Statement varchar(max)
    
            -- 1 = Will not execute statements 
     SET @Debug = 0
            -- 0 = Will not create or truncate storage table
            -- 1 = Will create or truncate storage table
     SET @Recycle = 0
            -- 1 = Will print a message on every step
     set @Verbose = 1
    
     SET @i = 1
        SET @CreateStatement = 'ALTER TABLE [dbo].[<tablename>]  WITH NOCHECK ADD  CONSTRAINT [<constraintname>] FOREIGN KEY([<column>]) REFERENCES [dbo].[<reftable>] ([<refcolumn>])'
        SET @DropStatement = 'ALTER TABLE [dbo].[<tablename>] DROP CONSTRAINT [<constraintname>]'
        SET @TruncateStatement = 'TRUNCATE TABLE [<tablename>]'
    
    -- Drop Temporary tables
    DROP TABLE #FKs
    
    -- GET FKs
    SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(parent_object_id), clm1.name) as ID,
           OBJECT_NAME(constraint_object_id) as ConstraintName,
           OBJECT_NAME(parent_object_id) as TableName,
           clm1.name as ColumnName, 
           OBJECT_NAME(referenced_object_id) as ReferencedTableName,
           clm2.name as ReferencedColumnName
      INTO #FKs
      FROM sys.foreign_key_columns fk
           JOIN sys.columns clm1 
             ON fk.parent_column_id = clm1.column_id 
                AND fk.parent_object_id = clm1.object_id
           JOIN sys.columns clm2
             ON fk.referenced_column_id = clm2.column_id 
                AND fk.referenced_object_id= clm2.object_id
     WHERE OBJECT_NAME(parent_object_id) not in ('//tables that you do not wont to be truncated')
     ORDER BY OBJECT_NAME(parent_object_id)
    
    
    -- Prepare Storage Table
    IF Not EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Internal_FK_Definition_Storage')
       BEGIN
            IF @Verbose = 1
         PRINT '1. Creating Process Specific Tables...'
    
      -- CREATE STORAGE TABLE IF IT DOES NOT EXISTS
      CREATE TABLE [Internal_FK_Definition_Storage] 
      (
       ID int not null identity(1,1) primary key,
       FK_Name varchar(250) not null,
       FK_CreationStatement varchar(max) not null,
       FK_DestructionStatement varchar(max) not null,
       Table_TruncationStatement varchar(max) not null
      ) 
       END 
    ELSE
       BEGIN
            IF @Recycle = 0
                BEGIN
                    IF @Verbose = 1
           PRINT '1. Truncating Process Specific Tables...'
    
        -- TRUNCATE TABLE IF IT ALREADY EXISTS
        TRUNCATE TABLE [Internal_FK_Definition_Storage]    
          END
          ELSE
             PRINT '1. Process specific table will be recycled from previous execution...'
       END
    
    IF @Recycle = 0
       BEGIN
    
      IF @Verbose = 1
         PRINT '2. Backing up Foreign Key Definitions...'
    
      -- Fetch and persist FKs             
      WHILE (@i <= (SELECT MAX(ID) FROM #FKs))
       BEGIN
        SET @ConstraintName = (SELECT ConstraintName FROM #FKs WHERE ID = @i)
        SET @TableName = (SELECT TableName FROM #FKs WHERE ID = @i)
        SET @ColumnName = (SELECT ColumnName FROM #FKs WHERE ID = @i)
        SET @ReferencedTableName = (SELECT ReferencedTableName FROM #FKs WHERE ID = @i)
        SET @ReferencedColumnName = (SELECT ReferencedColumnName FROM #FKs WHERE ID = @i)
    
        SET @DropStatementTemp = REPLACE(REPLACE(@DropStatement,'<tablename>',@TableName),'<constraintname>',@ConstraintName)
        SET @CreateStatementTemp = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@CreateStatement,'<tablename>',@TableName),'<column>',@ColumnName),'<constraintname>',@ConstraintName),'<reftable>',@ReferencedTableName),'<refcolumn>',@ReferencedColumnName)
        SET @TruncateStatementTemp = REPLACE(@TruncateStatement,'<tablename>',@TableName) 
    
        INSERT INTO [Internal_FK_Definition_Storage]
                            SELECT @ConstraintName, @CreateStatementTemp, @DropStatementTemp, @TruncateStatementTemp
    
        SET @i = @i + 1
    
        IF @Verbose = 1
           PRINT '  > Backing up [' + @ConstraintName + '] from [' + @TableName + ']'
    
       END
        END   
        ELSE 
           PRINT '2. Backup up was recycled from previous execution...'
    
           IF @Verbose = 1
         PRINT '3. Dropping Foreign Keys...'
    
        -- DROP FOREING KEYS
        SET @i = 1
        WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
              BEGIN
                 SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
        SET @Statement = (SELECT FK_DestructionStatement FROM [Internal_FK_Definition_Storage] WITH (NOLOCK) WHERE ID = @i)
    
        IF @Debug = 1 
           PRINT @Statement
        ELSE
           EXEC(@Statement)
    
        SET @i = @i + 1
    
        IF @Verbose = 1
           PRINT '  > Dropping [' + @ConstraintName + ']'
                 END     
    
        IF @Verbose = 1
           PRINT '4. Truncating Tables...'
    
        -- TRUNCATE TABLES
        SET @i = 1
        WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
              BEGIN
        SET @Statement = (SELECT Table_TruncationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    
        IF @Debug = 1 
           PRINT @Statement
        ELSE
           EXEC(@Statement)
    
        SET @i = @i + 1
    
        IF @Verbose = 1
           PRINT '  > ' + @Statement
              END
    
        IF @Verbose = 1
           PRINT '5. Re-creating Foreign Keys...'
    
        -- CREATE FOREING KEYS
        SET @i = 1
        WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
              BEGIN
                 SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
        SET @Statement = (SELECT FK_CreationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    
        IF @Debug = 1 
           PRINT @Statement
        ELSE
           EXEC(@Statement)
    
        SET @i = @i + 1
    
        IF @Verbose = 1
           PRINT '  > Re-creating [' + @ConstraintName + ']'
              END
    
        IF @Verbose = 1
           PRINT '6. Process Completed'
    
  • 51

    在网络上的其他地方找到

    EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
    EXEC sp_MSForEachTable 'ALTER TABLE ? DISABLE TRIGGER ALL'
    -- EXEC sp_MSForEachTable 'DELETE FROM ?' -- Uncomment to execute
    EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
    EXEC sp_MSForEachTable 'ALTER TABLE ? ENABLE TRIGGER ALL'
    
  • 6

    如果不删除约束,则无法截断表 . 禁用也不起作用 . 你需要放弃一切 . 我制作了一个删除所有约束的脚本,然后重新创建 .

    一定要把它包装在一个交易中;)

    SET NOCOUNT ON
    GO
    
    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
    
    --DROP CONSTRAINT:
    
    DECLARE @dynSQL varchar(MAX);
    
    DECLARE cur CURSOR FOR
    SELECT
    '
    ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
    DROP CONSTRAINT ' + ForeignKeyConstraintName + '
    '
    FROM
    @table
    
    OPEN cur
    
    FETCH cur into @dynSQL
    WHILE @@FETCH_STATUS = 0 
    BEGIN
        exec(@dynSQL)
        print @dynSQL
    
        FETCH cur into @dynSQL
    END
    CLOSE cur
    DEALLOCATE cur
    ---------------------
    
    
    
       --HERE GOES YOUR TRUNCATES!!!!!
       --HERE GOES YOUR TRUNCATES!!!!!
       --HERE GOES YOUR TRUNCATES!!!!!
    
        truncate table your_table
    
       --HERE GOES YOUR TRUNCATES!!!!!
       --HERE GOES YOUR TRUNCATES!!!!!
       --HERE GOES YOUR TRUNCATES!!!!!
    
    ---------------------
    --ADD CONSTRAINT:
    
    DECLARE cur2 CURSOR FOR
    SELECT
    '
    ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
    ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ')
    '
    FROM
    @table
    
    OPEN cur2
    
    FETCH cur2 into @dynSQL
    WHILE @@FETCH_STATUS = 0 
    BEGIN
        exec(@dynSQL)
    
        print @dynSQL
    
        FETCH cur2 into @dynSQL
    END
    CLOSE cur2
    DEALLOCATE cur2
    
  • 0
    SET FOREIGN_KEY_CHECKS = 0; 
    
    truncate table "yourTableName";
    
    SET FOREIGN_KEY_CHECKS = 1;
    
  • 10

    截断对我不起作用,删除重新种子是最好的出路 . 如果你们中的一些人需要迭代大量的表来执行删除重新设置,你可能会遇到一些没有表的问题 . 标识列,以下代码在尝试重新设定之前检查标识列是否存在

    EXEC ('DELETE FROM [schemaName].[tableName]')
        IF EXISTS (Select * from sys.identity_columns where object_name(object_id) = 'tableName')
        BEGIN
            EXEC ('DBCC CHECKIDENT ([schemaName.tableName], RESEED, 0)')
        END
    
  • 0

    即使使用FK约束,以下内容也适用于我,并将以下答案组合到 only drop the specified tables


    USE [YourDB];
    
    DECLARE @TransactionName varchar(20) = 'stopdropandroll';
    
    BEGIN TRAN @TransactionName;
    set xact_abort on; /* automatic rollback https://stackoverflow.com/a/1749788/1037948 */
        -- ===== DO WORK // =====
    
        -- dynamic sql placeholder
        DECLARE @SQL varchar(300);
    
        -- LOOP: https://stackoverflow.com/a/10031803/1037948
        -- list of things to loop
        DECLARE @delim char = ';';
        DECLARE @foreach varchar(MAX) = 'Table;Names;Separated;By;Delimiter' + @delim + 'AnotherName' + @delim + 'Still Another';
        DECLARE @token varchar(MAX);
        WHILE len(@foreach) > 0
        BEGIN
            -- set current loop token
            SET @token = left(@foreach, charindex(@delim, @foreach+@delim)-1)
            -- ======= DO WORK // ===========
    
            -- dynamic sql (parentheses are required): https://stackoverflow.com/a/989111/1037948
            SET @SQL = 'DELETE FROM [' + @token + ']; DBCC CHECKIDENT (''' + @token + ''',RESEED, 0);'; -- https://stackoverflow.com/a/11784890
            PRINT @SQL;
            EXEC (@SQL);
    
            -- ======= // END WORK ===========
            -- continue loop, chopping off token
            SET @foreach = stuff(@foreach, 1, charindex(@delim, @foreach+@delim), '')
        END
    
        -- ===== // END WORK =====
    -- review and commit
    SELECT @@TRANCOUNT as TransactionsPerformed, @@ROWCOUNT as LastRowsChanged;
    COMMIT TRAN @TransactionName;
    

    Note:

    我认为按照您希望删除的顺序声明表仍然有帮助(即首先杀死依赖项) . 如this answer所示,您可以用所有表替换循环特定名称

    EXEC sp_MSForEachTable 'DELETE FROM ?; DBCC CHECKIDENT (''?'',RESEED, 0);';
    
  • 284

    这是我对这个问题的解决方案 . 我用它来改变PK,但想法一样 . 希望这会有用)

    PRINT 'Script starts'
    
    DECLARE @foreign_key_name varchar(255)
    DECLARE @keycnt int
    DECLARE @foreign_table varchar(255)
    DECLARE @foreign_column_1 varchar(255)
    DECLARE @foreign_column_2 varchar(255)
    DECLARE @primary_table varchar(255)
    DECLARE @primary_column_1 varchar(255)
    DECLARE @primary_column_2 varchar(255)
    DECLARE @TablN varchar(255)
    
    -->> Type the primary table name
    SET @TablN = ''
    ---------------------------------------------------------------------------------------    ------------------------------
    --Here will be created the temporary table with all reference FKs
    ---------------------------------------------------------------------------------------------------------------------
    PRINT 'Creating the temporary table'
    select cast(f.name  as varchar(255)) as foreign_key_name
        , r.keycnt
        , cast(c.name as  varchar(255)) as foreign_table
        , cast(fc.name as varchar(255)) as  foreign_column_1
        , cast(fc2.name as varchar(255)) as foreign_column_2
        , cast(p.name as varchar(255)) as primary_table
        , cast(rc.name as varchar(255))  as primary_column_1
        , cast(rc2.name as varchar(255)) as  primary_column_2
        into #ConTab
        from sysobjects f
        inner join sysobjects c on  f.parent_obj = c.id 
        inner join sysreferences r on f.id =  r.constid
        inner join sysobjects p on r.rkeyid = p.id
        inner  join syscolumns rc on r.rkeyid = rc.id and r.rkey1 = rc.colid
        inner  join syscolumns fc on r.fkeyid = fc.id and r.fkey1 = fc.colid
        left join  syscolumns rc2 on r.rkeyid = rc2.id and r.rkey2 = rc.colid
        left join  syscolumns fc2 on r.fkeyid = fc2.id and r.fkey2 = fc.colid
        where f.type =  'F' and p.name = @TablN
     ORDER BY cast(p.name as varchar(255))
    ---------------------------------------------------------------------------------------------------------------------
    --Cursor, below, will drop all reference FKs
    ---------------------------------------------------------------------------------------------------------------------
    DECLARE @CURSOR CURSOR
    /*Fill in cursor*/
    
    PRINT 'Cursor 1 starting. All refernce FK will be droped'
    
    SET @CURSOR  = CURSOR SCROLL
    FOR
    select foreign_key_name
        , keycnt
        , foreign_table
        , foreign_column_1
        , foreign_column_2
        , primary_table
        , primary_column_1
        , primary_column_2
        from #ConTab
    
    OPEN @CURSOR
    
    FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table,         @foreign_column_1, @foreign_column_2, 
                            @primary_table, @primary_column_1, @primary_column_2
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
    
        EXEC ('ALTER TABLE ['+@foreign_table+'] DROP CONSTRAINT ['+@foreign_key_name+']')
    
    FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table, @foreign_column_1, @foreign_column_2, 
                             @primary_table, @primary_column_1, @primary_column_2
    END
    CLOSE @CURSOR
    PRINT 'Cursor 1 finished work'
    ---------------------------------------------------------------------------------------------------------------------
    --Here you should provide the chainging script for the primary table
    ---------------------------------------------------------------------------------------------------------------------
    
    PRINT 'Altering primary table begin'
    
    TRUNCATE TABLE table_name
    
    PRINT 'Altering finished'
    
    ---------------------------------------------------------------------------------------------------------------------
    --Cursor, below, will add again all reference FKs
    --------------------------------------------------------------------------------------------------------------------
    
    PRINT 'Cursor 2 starting. All refernce FK will added'
    SET @CURSOR  = CURSOR SCROLL
    FOR
    select foreign_key_name
        , keycnt
        , foreign_table
        , foreign_column_1
        , foreign_column_2
        , primary_table
        , primary_column_1
        , primary_column_2
        from #ConTab
    
    OPEN @CURSOR
    
    FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table, @foreign_column_1, @foreign_column_2, 
                             @primary_table, @primary_column_1, @primary_column_2
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
    
        EXEC ('ALTER TABLE [' +@foreign_table+ '] WITH NOCHECK ADD  CONSTRAINT [' +@foreign_key_name+ '] FOREIGN KEY(['+@foreign_column_1+'])
            REFERENCES [' +@primary_table+'] (['+@primary_column_1+'])')
    
        EXEC ('ALTER TABLE [' +@foreign_table+ '] CHECK CONSTRAINT [' +@foreign_key_name+']')
    
    FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table, @foreign_column_1, @foreign_column_2, 
                             @primary_table, @primary_column_1, @primary_column_2
    END
    CLOSE @CURSOR
    PRINT 'Cursor 2 finished work'
    ---------------------------------------------------------------------------------------------------------------------
    PRINT 'Temporary table droping'
    drop table #ConTab
    PRINT 'Finish'
    
  • 76

    对于 MS SQL ,至少是较新的版本,您可以使用以下代码禁用约束:

    ALTER TABLE Orders
    NOCHECK CONSTRAINT [FK_dbo.Orders_dbo.Customers_Customer_Id]
    GO
    
    TRUNCATE TABLE Customers
    GO
    
    ALTER TABLE Orders
    WITH CHECK CHECK CONSTRAINT [FK_dbo.Orders_dbo.Customers_Customer_Id]
    GO
    
  • -3

    如果这些答案都不像我的情况那样有效:

    • 删除约束

    • 设置所有值以允许空值

    • 截断表

    • 添加已删除的约束 .

    祝好运!

  • 9

    我写了以下几种方法并试图对它们进行参数化,所以 you canQuery documentMake a useful SP with them easily 中运行它们 .

    A)删除

    If 你的 table has not millions of records 这很好用 hasn't any Alter commands

    ---------------------------------------------------------------
    ------------------- Just Fill Parameters Value ----------------
    ---------------------------------------------------------------
    DECLARE @DbName AS NVARCHAR(30) = 'MyDb'         --< Db Name
    DECLARE @Schema AS NVARCHAR(30) = 'dbo'          --< Schema
    DECLARE @TableName AS NVARCHAR(30) = 'Book'      --< Table Name
    ------------------ /Just Fill Parameters Value ----------------
    
    DECLARE @Query AS NVARCHAR(500) = 'Delete FROM ' + @TableName
    
    EXECUTE sp_executesql @Query
    SET @Query=@DbName+'.'+@Schema+'.'+@TableName
    DBCC CHECKIDENT (@Query,RESEED, 0)
    

    在我的上述答案中,解决问题中提到的问题的方法是基于@ s15199d的答案 .

    B)截断

    If 您的表 has millions of records 或者您的代码中的 Alter command 没有任何问题,请使用以下代码:

    --   Book                               Student
    --
    --   |  BookId  | Field1 |              | StudentId |  BookId  |
    --   ---------------------              ------------------------ 
    --   |    1     |    A   |              |     2     |    1     |  
    --   |    2     |    B   |              |     1     |    1     |
    --   |    3     |    C   |              |     2     |    3     |  
    
    ---------------------------------------------------------------
    ------------------- Just Fill Parameters Value ----------------
    ---------------------------------------------------------------
    DECLARE @DbName AS NVARCHAR(30) = 'MyDb'
    DECLARE @Schema AS NVARCHAR(30) = 'dbo'
    DECLARE @TableName_ToTruncate AS NVARCHAR(30) = 'Book'
    
    DECLARE @TableName_OfOwnerOfConstraint AS NVARCHAR(30) = 'Student' --< Decelations About FK_Book_Constraint
    DECLARE @Ref_ColumnName_In_TableName_ToTruncate AS NVARCHAR(30) = 'BookId' --< Decelations About FK_Book_Constraint
    DECLARE @FK_ColumnName_In_TableOfOwnerOfConstraint AS NVARCHAR(30) = 'Fk_BookId' --< Decelations About FK_Book_Constraint
    DECLARE @FK_ConstraintName AS NVARCHAR(30) = 'FK_Book_Constraint'                --< Decelations About FK_Book_Constraint
    ------------------ /Just Fill Parameters Value ----------------
    
    DECLARE @Query AS NVARCHAR(2000)
    
    SET @Query= 'ALTER TABLE '+@TableName_OfOwnerOfConstraint+' DROP CONSTRAINT '+@FK_ConstraintName
    EXECUTE sp_executesql @Query
    
    SET @Query= 'Truncate Table '+ @TableName_ToTruncate
    EXECUTE sp_executesql @Query
    
    SET @Query= 'ALTER TABLE '+@TableName_OfOwnerOfConstraint+' ADD CONSTRAINT '+@FK_ConstraintName+' FOREIGN KEY('+@FK_ColumnName_In_TableOfOwnerOfConstraint+') REFERENCES '+@TableName_ToTruncate+'('+@Ref_ColumnName_In_TableName_ToTruncate+')'
    EXECUTE sp_executesql @Query
    

    在我的上述答案中,解决问题中提到的问题的方法是基于@LauroWolffValenteSobrinho的回答 . 如果您有多个CONSTRAINT,那么您应该像我一样将其代码附加到上面的查询中 . 您还可以更改上面的代码库@SerjSagan,以禁用启用约束

  • 3

    在SSMS中,我打开了图表,显示了密钥 . 删除密钥并截断文件后,我刷新然后重新关注图表并通过清除然后恢复身份框创建更新 . 保存图表会显示一个“保存”对话框,而不是“在工作地点时对数据库进行了更改”对话框,单击“是”将“还原”键从图中的锁定副本还原 .

  • -3

    如果你在任何频率上这样做,甚至按计划进行,我会 absolutely, unequivocally never use a DML statement. 写入事务日志的成本只是高,并将整个数据库设置为 SIMPLE 恢复模式以截断一个表是荒谬的 .

    不幸的是,最好的方法是艰苦或艰苦的方式 . 那是:

    • 删除约束

    • 截断表

    • 重新创建约束

    我这样做的过程包括以下步骤:

    • 在SSMS中右键单击相关表,然后选择“查看依赖关系”

    • 记下引用的表格(如果有的话)

    • 返回对象资源管理器,展开“密钥”节点并记下外键(如果有)

    • 开始编写脚本(删除/截断/重新创建)

    这种性质的脚本应该在 begin trancommit tran 块内完成 .

  • 4

    你可以试试 DELETE FROM <your table >; .

    服务器将显示限制名称和表格,删除该表格可以删除所需内容 .

  • 1

    我刚刚发现只要先禁用 child 表上的约束,就可以在父表上使用TRUNCATE表,并对子进行外键约束 . 例如 .

    子表上的外键CONSTRAINT child_par_ref,引用PARENT_TABLE

    ALTER TABLE CHILD_TABLE DISABLE CONSTRAINT child_par_ref;
    TRUNCATE TABLE CHILD_TABLE;
    TRUNCATE TABLE PARENT_TABLE;
    ALTER TABLE CHILD_TABLE ENABLE CONSTRAINT child_par_ref;
    
  • 17

    最简单的方法:
    1 - 输入phpmyadmin
    2 - 单击左列中的表名称
    3 - 单击操作(顶层菜单)
    4 - 单击“清空表格(TRUNCATE)”
    5 - 禁用框"Enable foreign key checks"
    6 - 完成!

    链接到图像教程
    Tutorial: http://www.imageno.com/wz6gv1wuqajrpic.html
    (抱歉,我没有足够的声誉来上传图片:P)

  • 4
    SET FOREIGN_KEY_CHECKS=0;
    TRUNCATE table1;
    TRUNCATE table2;
    SET FOREIGN_KEY_CHECKS=1;
    

    参考 - truncate foreign key constrained table

    在MYSQL为我工作

相关问题