由于存在外键约束,无法截断表格?

582

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

我知道我可以:

  • 使用没有where条件的DELETE,然后RESEED标识符(或)
  • 删除FK,截断表并重新创建FK。

我以为只要在父表之前截断了子表,我可以不执行上述任何选项,但我收到以下错误:

Cannot truncate table 'TableName' because it is being referenced by a FOREIGN KEY constraint.


31个回答

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

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


3
我建议不要选择这个方法,因为你可能会遇到这个错误:DELETE 语句与 REFERENCE 约束冲突。 - sksallaj
对我没有用。仍然出现“DELETE 语句与 REFERENCE 约束冲突”的错误。 - emirhosseini
1
这比移除和添加约束更为直接。我将其作为主数据 SQL 脚本的初始设置之一。 - Balaji Birajdar
1
@emirhosseini 很晚才加入派对,但以防其他人遇到同样的问题,那可能是因为您仍然有记录在另一个表中引用您正在尝试删除的行。如果您首先删除这些行(或配置级联删除),那么您就不会再收到该错误,并且来自此答案的说明应该可以正常工作。 - Rui Taborda
对我有用,如果表没有标识列,它将抛出一个错误,但会正常继续。 - Hasan Shouman
这个解决方案是至少对于非生产数据库来说最简单的方式。 - Vertigo

454

正确的做法是:如果一个表上有外键约束,那么你不能对其进行截断操作。

通常我的处理流程如下:

  1. 删除约束
  2. 截断表
  3. 重新创建约束

(当然,这一切都在一个事务中完成。)

当然,这只适用于子表已经被截断的情况。否则,我会根据我的数据情况采取不同的路线。(这里有太多的变量,无法一一详细介绍。)

原始帖子已经确定了为什么会出现这种情况;更多详细信息请参见此答案


95
“DELETE FROM”语句不会重置自增列,而“TRUNCATE”语句会。它们在功能上并不相同。 - robross0606
56
如果你要删除大量数据,那么"截断(Truncate)"通常是你想要的操作。需要截断一百万行?十亿行?只需1毫秒...所以@M07,请不要说"使用delete语句更加规范",因为这完全不准确。 - ctb
3
删除大量数据后,用户需要收缩表格和日志文件以回收磁盘空间。 - Muhammad Yousaf Sulahria
3
通常情况下,不建议使用魔法缩小按钮(或脚本),这在99%的情况下都是如此。 - Tom Stickel
1
要删除并重新创建约束,您需要特殊的权限。我相信这需要比在MySQL中截断所需的权限更多。因此,这使得以编程方式执行此操作更加困难,除非您想为程序提供“完全控制权”以执行几乎所有操作。这违反了最后的访问权限规则。 - John Foll
显示剩余8条评论

270

由于TRUNCATE TABLE是一个DDL命令,所以它无法检查表中的记录是否被子表中的记录引用。

这就是为什么DELETE可以工作而TRUNCATE TABLE不能:因为数据库能够确保它没有被另一条记录引用。


121

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

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


3
在使用DELETE FROM语句之后,如果使用resead新值=1,则会从ID 2开始而不是从1开始。如果表在创建后没有插入任何行,或者使用TRUNCATE TABLE语句删除了所有行,则在运行DBCC CHECKIDENT后插入的第一行将使用new_reseed_value作为标识。否则,插入的下一行将使用new_reseed_value + 当前增量值。 - Zoran P.
@ZoranP,请查看存储过程变体:https://github.com/reduardo7/TableTruncate - Eduardo Cuomo
6
DBCC CHECKIDENT([TableName], RESEED, 0)的意思是重新设置表中自增列的初始值为0,而不是1。 - Tico Fortes
1
@TicoFortes 帖子已更新。请查看存储过程变体。 - Eduardo Cuomo
2
这不是一个好的方法。正如其他700个版本对这个问题的相同回答所评论的那样,除非你的数据库处于简单恢复模式下,以限制事务日志记录。 - pim

93

@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

14
这个回答值得更多的投票!事实上,如果我能的话,我很愿意给你买一杯啤酒,彼得 :) - nsimeonov
4
谢谢您提供这段代码。但是请注意,您应该添加其他逻辑来检查禁用的外键(FK)。否则,您将启用当前已禁用的约束条件。 - Andre Figueiredo
3
我按照 @AndreFigueiredo 的建议制作了一个版本,并将其放在了 GitLab 上:https://gitlab.com/ranolfi/truncate-referenced-table。请随意将代码合并到你的答案中。 - Marc.2377
2
这很棒,但请注意,如果您的表不在默认(dbo)模式中,则无法正常工作。 - Irwene
1
为了适应复合键、多个模式和级联删除,我对其进行了编辑。https://dev59.com/C3VC5IYBdhLWcg3wjx_u#54353773 - GhotiPhud
显示剩余3条评论

23

好的,由于我没有找到我使用的非常简单的解决方案的示例,所以我需要进行翻译,具体步骤如下:

  1. 删除外键;
  2. 清空表格
  3. 重新创建外键

下面是具体步骤:

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)

就是这样。


1
如果您有多个带有外键引用的表,则此方法无法正常工作。您将不得不在整个数据库中删除许多外键约束。 - jbright
我收到了 Msg 3728, Level 16, State 1, Line 1 'FK_User_UserTypeID' 不是一个约束。 Msg 3727, Level 16, State 0, Line 1 无法删除约束。请参阅先前的错误。 - Moeez

22

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

TRUNCATE TABLE table_name;

delete from tablename

DBCC CHECKIDENT ('tablename', RESEED, 0)

编辑:更正了 SQL Server 的语法。


13
“TRUNCATE” 可以避免记录日志,对于大型表来说比“DELETE”要快得多。因此,这并不是一个真正等效的解决方案。 - siride
7
这个答案与那个答案有何不同?前者是在一年前给出的。 - Ofer Zelig

21

这个过程是先移除外键约束和截断表,然后按照以下步骤添加约束。

仅适用于MySQL。

SET FOREIGN_KEY_CHECKS = 0; 

truncate table "yourTableName";

SET FOREIGN_KEY_CHECKS = 1;

36
这个问题涉及到 MS SQL Server,它没有 FOREIGN_KEY_CHECKS 设置。 - Elezar
3
我认为这可以在MySQL上实现,但在MS SQL Server上不行。 - Cocowalla
6
这个回答应该被删除。它与所讨论的系统——MS SQL Server无关,只会导致混淆。 - mpalmer78
我在搜索MySQL时找到了这个问题线程,因此这个答案非常有用。谢谢。也许更新一下你的答案,说明它是针对MySQL的。 - Shani Kehati

13

这是我编写的一段脚本,旨在自动化该过程。希望能对您有所帮助。

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'

2
小心。我建议在你的脚本中添加键的引用操作,否则你将失去级联设置。 - alphadogg
1
这个对我没用,但我喜欢它的精神,所以我修改了一些东西:将其制作成存储过程 更改了外键填充和重新创建的方式 原始脚本截断了所有引用表,当引用表不能被截断时,这可能是错误的,因为它也具有外键引用。在此版本中,只有指定为参数的表将被截断,所有引用表应在调用此脚本之前手动截断我将更新的解决方案发布到了这个线程中 https://dev59.com/C3VC5IYBdhLWcg3wjx_u#13249209 - Peter Szanto
1
@alphadogg 有没有办法找到这些引用操作?我在网上搜索了一下,似乎找不到。如果您愿意,我可以将其发布为正式问题。 - Michael
2
未来的访问者注意:它在 sys.foreign_keys 表中。(参考链接:http://technet.microsoft.com/en-us/library/ms186973(v=sql.105).aspx) - Michael
1
@Michael:你也可以使用INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS(http://msdn.microsoft.com/en-us/library/ms179987.aspx)来查询相关约束。 - alphadogg
为了适应复合键、多个模式和级联删除,我对其进行了编辑。https://dev59.com/C3VC5IYBdhLWcg3wjx_u#54353773 - GhotiPhud

13

你可以按照以下步骤操作,通过重新填充表格来删除表格中的数据。

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

如果出现错误,那么您需要重新生成主表。


3
请记住,尽管这个方法效果很好,但与“截断表”只在事务日志中添加一条记录相比,事务日志将按表中的记录数增加。对于大多数表格来说不是什么大问题,但如果有数百万行,则可能会成为一个问题。 - BeanFlicker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接