【问题标题】:SQL delete records in orderSQL按顺序删除记录
【发布时间】:2016-08-07 15:26:20
【问题描述】:

给定表结构:

Comment
-------------
ID (PK)
ParentCommentID (FK)

我想运行DELETE FROM Comments 来删除所有记录。

但是,如果在子 cmets 之前删除了父评论,则与父评论记录的关系会产生 FK 冲突。

要解决此问题,可以按相反的 ID 顺序删除。如何以相反的ID顺序删除表中的所有记录?

【问题讨论】:

  • 禁用外键和截断表,启用FK。
  • 用 CASCADE 更新外键
  • 查看之前的SO answer。基本上删除当前的 FK 约束并使用级联删除选项重新添加它。这将允许一次删除从两个表中删除记录。
  • 使用truncate table Comment?

标签: sql sql-server sql-delete


【解决方案1】:

对于单独的父表和子表,ON DELETE CASCADE 将确保删除父表也会删除子表。当两组数据都在同一个表中时,它是否有效?也许吧,我很想知道!

How do I use cascade delete with SQL server.

【讨论】:

    【解决方案2】:

    这可行(您可以尝试将子查询替换为 top...)

    create table #a1 (i1 int identity, b1 char(5))
    insert into #a1 values('abc')
    go 5 
    
    while ( (select count(*) from #a1 ) > 0)
        begin 
         delete from #a1 where i1=(select top 1 i1 from #a1 order by i1 desc)
    
        end
    

    【讨论】:

      【解决方案3】:

      以下将删除所有本身不是父项的行。如果表很大并且 ParentCommentID 上没有索引,则可能需要一段时间才能运行...

      DELETE Comment
       from Comment co
       where not exists (--  Correlated subquery
                         select 1
                          from Comment
                          where ParentCommentID = co.ID)
      

      如果表确实很大,那么大删除可能会对您的系统造成不利影响,例如锁定表和使事务日志文件膨胀。以下将限制将删除的行数:

      DELETE top (1000) Comment  --  (1000 is not very many)
       from Comment co
       where not exists (--  Correlated subquery
                         select 1
                          from Comment
                          where ParentCommentID = co.ID)
      

      由于删除一些但不是全部可能没有那么有用,这里有一个循环结构,它将一直持续到一切都消失:

      DECLARE @Done int = 1
      
      --BEGIN TRANSACTION
      
      WHILE @Done > 0
       BEGIN
          --  Loop until nothing left to delete
          DELETE top (1000) Comment
           from Comment co
           where not exists (--  Correlated subquery
                             select 1
                              from Comment
                              where ParentCommentID = co.ID)
          SET @Done = @@Rowcount
      
       END
      
      --ROLLBACK
      

      当然,最后一个是危险的(注意用于测试的开始/结束事务!)您需要WHERE 子句来限制删除的内容,以及确保您不会以某种方式遇到无限循环——所有细节取决于你的数据和情况。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-04
        • 1970-01-01
        • 2014-10-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多