代码之家  ›  专栏  ›  技术社区  ›  ctrlShiftBryan

无法截断表,因为它正被外键约束引用?

  •  378
  • ctrlShiftBryan  · 技术社区  · 17 年前

    我知道我也可以

    • DELETE 没有where子句,然后 RESEED 身份(或)
    • 删除FK,截断表,然后重新创建FK。

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

    无法截断表“TableName”,因为它正被外键约束引用。

    27 回复  |  直到 12 年前
        1
  •  426
  •   Community Mohan Dere    9 年前

    对的不能截断具有FK约束的表。

    通常,我的流程是:

    1. Trunc桌子

    (当然,这一切都是在交易中发生的。)

    当然,这仅适用于以下情况: 子项已被截断。 否则我会走另一条路,完全取决于数据的外观。(变量太多,无法进入此处。)

    this answer 更多细节。

        2
  •  425
  •   Ofer Zelig Tom    8 年前
    DELETE FROM TABLENAME
    DBCC CHECKIDENT ('DATABASENAME.dbo.TABLENAME',RESEED, 0)
    

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

        3
  •  232
  •   Michael come lately PhiLho    12 年前

    因为 TRUNCATE TABLE 是一个 DDL command ,它无法检查表中的记录是否被子表中的记录引用。

    这就是为什么 DELETE 作品及 截断表 不:因为数据库能够确保它没有被其他记录引用。

        4
  •  112
  •   Espo    7 年前

    没有 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)
    

    作为存储过程

    https://github.com/reduardo7/TableTruncate

    笔记 如果你有数百万条以上的记录,这可能不是你想要的,因为它非常慢。

        5
  •  82
  •   Peter Szanto    9 年前

    • 使其成为存储过程
    • 更改了填充和重新创建外键的方式
    • 原始脚本截断所有引用的表,当引用的表具有其他外键引用时,这可能会导致外键冲突错误。此脚本仅截断指定为参数的表。由用户按照正确的顺序对所有表多次调用此存储过程

    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
    
        6
  •  22
  •   Sean Glover    13 年前

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

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

    编辑:已更正SQL Server的语法

        7
  •  21
  •   Lauro Wolff Valente Sobrinho    12 年前

    好吧,既然我没有找到 的 很简单

    1. 截断表
    2. 重新创建外键

    下面是:

    ID ,从桌上 TABLE_OWNING_CONSTRAINT ) 2) 从表中删除该键:

    ALTER TABLE TABLE_OWNING_CONSTRAINT DROP CONSTRAINT FK_PROBLEM_REASON
    

    3) 截断表

    TRUNCATE TABLE TABLE_TO_TRUNCATE
    

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

    就这样。

        8
  •  19
  •   Vengadesh KS Victor Jimenez    5 年前

    该过程正在删除外键约束并截断表 然后通过以下步骤添加约束。

        SET FOREIGN_KEY_CHECKS = 0; 
    
        truncate table "yourTableName";
    
        SET FOREIGN_KEY_CHECKS = 1;
    
        9
  •  14
  •   Hamad    12 年前

    通过 reseeding table

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

    如果出现错误,则必须重新设置主表的种子。

        10
  •  13
  •   denver_citizen    16 年前

    下面是我编写的一个脚本,用于自动化该过程。我希望有帮助。

    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'
    
        11
  •  9
  •   Xaratas GhotiPhud    6 年前

    @丹佛大学公民和@Peter Szanto的答案对我来说不太合适,但我修改了它们以说明:

    1. 关于删除和更新操作
    2. 重新添加时检查索引
    3. dbo以外的模式
    4. 一次多个表
    DECLARE @Debug bit = 0;
    
    -- List of tables to truncate
    select
        SchemaName, Name
    into #tables
    from (values 
        ('schema', 'table')
        ,('schema2', 'table2')
    ) as X(SchemaName, Name)
    
    
    BEGIN TRANSACTION TruncateTrans;
    
    with foreignKeys AS (
         SELECT 
            SCHEMA_NAME(fk.schema_id) as SchemaName
            ,fk.Name as ConstraintName
            ,OBJECT_NAME(fk.parent_object_id) as TableName
            ,SCHEMA_NAME(t.SCHEMA_ID) as ReferencedSchemaName
            ,OBJECT_NAME(fk.referenced_object_id) as ReferencedTableName
            ,fc.constraint_column_id
            ,COL_NAME(fk.parent_object_id, fc.parent_column_id) AS ColumnName
            ,COL_NAME(fk.referenced_object_id, fc.referenced_column_id) as ReferencedColumnName
            ,fk.delete_referential_action_desc
            ,fk.update_referential_action_desc
        FROM sys.foreign_keys AS fk
            JOIN sys.foreign_key_columns AS fc
                ON fk.object_id = fc.constraint_object_id
            JOIN #tables tbl 
                ON OBJECT_NAME(fc.referenced_object_id) = tbl.Name
            JOIN sys.tables t on OBJECT_NAME(t.object_id) = tbl.Name 
                and SCHEMA_NAME(t.schema_id) = tbl.SchemaName
                and t.OBJECT_ID = fc.referenced_object_id
    )
    
    
    
    select
        quotename(fk.ConstraintName) AS ConstraintName
        ,quotename(fk.SchemaName) + '.' + quotename(fk.TableName) AS TableName
        ,quotename(fk.ReferencedSchemaName) + '.' + quotename(fk.ReferencedTableName) AS ReferencedTableName
        ,replace(fk.delete_referential_action_desc, '_', ' ') AS DeleteAction
        ,replace(fk.update_referential_action_desc, '_', ' ') AS UpdateAction
        ,STUFF((
            SELECT ',' + quotename(fk2.ColumnName)
            FROM foreignKeys fk2 
            WHERE fk2.ConstraintName = fk.ConstraintName and fk2.SchemaName = fk.SchemaName
            ORDER BY fk2.constraint_column_id
            FOR XML PATH('')
        ),1,1,'') AS ColumnNames
        ,STUFF((
            SELECT ',' + quotename(fk2.ReferencedColumnName)
            FROM foreignKeys fk2 
            WHERE fk2.ConstraintName = fk.ConstraintName and fk2.SchemaName = fk.SchemaName
            ORDER BY fk2.constraint_column_id
            FOR XML PATH('')
        ),1,1,'') AS ReferencedColumnNames
    into #FKs
    from foreignKeys fk
    GROUP BY fk.SchemaName, fk.ConstraintName, fk.TableName, fk.ReferencedSchemaName, fk.ReferencedTableName, fk.delete_referential_action_desc, fk.update_referential_action_desc
    
    
    
    -- Drop FKs
    select 
        identity(int,1,1) as ID,
        'ALTER TABLE ' + fk.TableName + ' DROP CONSTRAINT ' + fk.ConstraintName AS script
    into #scripts
    from #FKs fk
    
    -- Truncate 
    insert into #scripts
    select distinct 
        'TRUNCATE TABLE ' + quotename(tbl.SchemaName) + '.' + quotename(tbl.Name) AS script
    from #tables tbl
    
    -- Recreate
    insert into #scripts
    select 
        'ALTER TABLE ' + fk.TableName + 
        ' WITH CHECK ADD CONSTRAINT ' + fk.ConstraintName + 
        ' FOREIGN KEY ('+ fk.ColumnNames +')' + 
        ' REFERENCES ' + fk.ReferencedTableName +' ('+ fk.ReferencedColumnNames +')' +
        ' ON DELETE ' + fk.DeleteAction COLLATE Latin1_General_CI_AS_KS_WS + ' ON UPDATE ' + fk.UpdateAction COLLATE Latin1_General_CI_AS_KS_WS AS script
    from #FKs fk
    
    
    DECLARE @script nvarchar(MAX);
    
    DECLARE curScripts CURSOR FOR 
        select script
        from #scripts
        order by ID
    
    OPEN curScripts
    
    WHILE 1=1 BEGIN
        FETCH NEXT FROM curScripts INTO @script
        IF @@FETCH_STATUS != 0 BREAK;
    
        print @script;
        IF @Debug = 0
            EXEC (@script);
    END
    CLOSE curScripts
    DEALLOCATE curScripts
    
    
    drop table #scripts
    drop table #FKs
    drop table #tables
    
    
    COMMIT TRANSACTION TruncateTrans;
    
        12
  •  8
  •   renanleandrof    13 年前

    确保将其包装在事务中;)

    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
    
        13
  •  8
  •   Michael come lately PhiLho    12 年前

    如果我理解正确,你会怎么做 希望 要做的是为涉及集成测试的DB建立一个干净的环境。

    我在这里的方法是删除整个模式,然后重新创建它。

    原因:

    1. 您可能已经有了一个“创建模式”脚本。重新使用它进行测试隔离很容易。
    2. 创建模式非常快。
        14
  •  6
  •   Dan Atkinson    13 年前

    在网上其他地方可以找到

    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'
    
        15
  •  5
  •   Ji_in_coding    10 年前

    truncate对我不起作用,删除+重新设定种子是最好的解决方法。 如果有些人需要迭代大量的表来执行delete+reseed,您可能会遇到一些没有标识列的表的问题,下面的代码会在尝试重新设置标识列之前检查标识列是否存在

        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
    
        16
  •  5
  •   Ramin Bateni    9 年前

    我编写了以下方法并尝试将它们参数化,因此 你可以 把它们放在一个盒子里 Query document 作出有用的决定 SP 与他们轻松相处 .

    A) 删除

    如果 你的桌子 这是一个好办法 没有任何更改命令 :

    ---------------------------------------------------------------
    ------------------- 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)
    
    • 在我的上述回答中,解决问题中提到的问题的方法是基于 answer .

    如果 你的桌子 有数百万张唱片 改变命令 在代码中,然后使用以下代码:

    --   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
    
    • 在我的上述回答中,解决问题中提到的问题的方法是基于 @劳沃夫瓦伦泰索布林霍 answer .

    • 您还可以更改上述代码库 answer

        17
  •  4
  •   Ehsan Mirsaeedi    6 年前

    唯一的方法是在执行截断之前删除外键。在截断数据之后,必须重新创建索引。

    以下脚本生成删除所有外键约束所需的SQL。

    DECLARE @drop NVARCHAR(MAX) = N'';
    
    SELECT @drop += N'
    ALTER TABLE ' + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) 
        + ' DROP CONSTRAINT ' + QUOTENAME(fk.name) + ';'
    FROM sys.foreign_keys AS fk
    INNER JOIN sys.tables AS ct
      ON fk.parent_object_id = ct.[object_id]
    INNER JOIN sys.schemas AS cs 
      ON ct.[schema_id] = cs.[schema_id];
    
    SELECT @drop
    

    接下来,以下脚本生成重新创建外键所需的SQL。

    DECLARE @create NVARCHAR(MAX) = N'';
    
    SELECT @create += N'
    ALTER TABLE ' 
       + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) 
       + ' ADD CONSTRAINT ' + QUOTENAME(fk.name) 
       + ' FOREIGN KEY (' + STUFF((SELECT ',' + QUOTENAME(c.name)
       -- get all the columns in the constraint table
        FROM sys.columns AS c 
        INNER JOIN sys.foreign_key_columns AS fkc 
        ON fkc.parent_column_id = c.column_id
        AND fkc.parent_object_id = c.[object_id]
        WHERE fkc.constraint_object_id = fk.[object_id]
        ORDER BY fkc.constraint_column_id 
        FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'')
      + ') REFERENCES ' + QUOTENAME(rs.name) + '.' + QUOTENAME(rt.name)
      + '(' + STUFF((SELECT ',' + QUOTENAME(c.name)
       -- get all the referenced columns
        FROM sys.columns AS c 
        INNER JOIN sys.foreign_key_columns AS fkc 
        ON fkc.referenced_column_id = c.column_id
        AND fkc.referenced_object_id = c.[object_id]
        WHERE fkc.constraint_object_id = fk.[object_id]
        ORDER BY fkc.constraint_column_id 
        FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') + ');'
    FROM sys.foreign_keys AS fk
    INNER JOIN sys.tables AS rt -- referenced table
      ON fk.referenced_object_id = rt.[object_id]
    INNER JOIN sys.schemas AS rs 
      ON rt.[schema_id] = rs.[schema_id]
    INNER JOIN sys.tables AS ct -- constraint table
      ON fk.parent_object_id = ct.[object_id]
    INNER JOIN sys.schemas AS cs 
      ON ct.[schema_id] = cs.[schema_id]
    WHERE rt.is_ms_shipped = 0 AND ct.is_ms_shipped = 0;
    
    SELECT @create
    

    运行生成的脚本删除所有外键,截断表,然后运行生成的脚本重新创建所有外键。

    这些查询来自 here .

        18
  •  3
  •   andrewsi Laxman Battini    14 年前

    这是我解决这个问题的办法。我用它来改变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'
    
        19
  •  3
  •   Serj Sagan    13 年前

    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
    
        20
  •  3
  •   Community Mohan Dere    9 年前

    以下内容即使在使用FK约束的情况下也适用于我,并结合了以下问题的答案: 只删除指定的表 :


    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;
    

    注:

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

    EXEC sp_MSForEachTable 'DELETE FROM ?; DBCC CHECKIDENT (''?'',RESEED, 0);';
    
        21
  •  2
  •   j.rmz87    12 年前

    如果这些答案中没有一个与我的情况类似,请执行以下操作:

    1. 删除约束
    2. 将所有值设置为允许空值
    3. 添加已删除的约束。

    祝你好运

        22
  •  1
  •   mwafi    7 年前

    delete from tablename;
    

    然后

    ALTER TABLE tablename AUTO_INCREMENT = 1;
    
        23
  •  0
  •   user2584621    12 年前

        24
  •  0
  •   pim    9 年前

    如果你以任何频率做这件事,即使是在日程安排上,我也会这么做 绝对,绝对不要使用DML语句。 写入事务日志的成本非常高,将整个数据库设置为 SIMPLE 截断一个表的恢复模式是荒谬的。

    不幸的是,最好的方法是艰难或艰苦的方法。即:

    • 截断表
    • 重新创建约束

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

    1. 在SSMS中,右键单击相关表格,然后选择 查看依赖项
    2. 钥匙 节点并记下外键(如果有)
    3. 开始编写脚本(删除/截断/重新创建)

    这种性质的剧本 应该 begin tran commit tran 块

        25
  •  0
  •   NM Naufaldo    5 年前

    这是一个使用实体框架的示例

    • 要重置的表: Foo

    • 另一个表取决于: Bar

    • 表上的约束列 : FooColumn

    • 表上的约束列 : BarColumn

       public override void Down()
       {
           DropForeignKey("dbo.Bar", "BarColumn", "dbo.Foo");
           Sql("TRUNCATE TABLE Foo");
           AddForeignKey("dbo.Bar", "BarColumn", "dbo.Foo", "FooColumn", cascadeDelete: true);
       }
      
        26
  •  -4
  •   Martijn Pieters    13 年前

    DELETE FROM <your table >; .

    服务器将向您显示限制和表的名称,删除该表可以删除您需要的内容。

        27
  •  -4
  •   PWF    12 年前

    小孩 先上桌。 例如。

    外键约束子表上的子表,引用父表

    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;
    
        28
  •  -4
  •   Marco    10 年前


    1-输入phpmyadmin
    2-单击左列中的表名

    4-单击“清空表格(截断)”
    5-禁用“启用外键检查”框
    6-完成!


    Tutorial: http://www.imageno.com/wz6gv1wuqajrpic.html
    (对不起,我没有足够的声誉在这里上传图片:P)

        29
  •  -6
  •   Community Mohan Dere    9 年前
    SET FOREIGN_KEY_CHECKS=0;
    TRUNCATE table1;
    TRUNCATE table2;
    SET FOREIGN_KEY_CHECKS=1;
    

    truncate foreign key constrained table

    在MYSQL中为我工作

    推荐文章