【问题标题】:SQL Server 2008 Delete Records from Self-Referencing Table in correct order [duplicate]SQL Server 2008以正确的顺序从自引用表中删除记录[重复]
【发布时间】:2012-08-31 15:30:29
【问题描述】:

可能重复:
SQL: DELETE data from self-referencing table in specific order

我需要从 SQL Server 2008 中的自引用表中删除一组记录。我正在尝试执行以下操作,但它不喜欢 order by。

WITH SelfReferencingTable (ID, depth)
AS
(
   SELECT id, 0 as [depth]
   FROM dbo.Table
   WHERE parentItemID IS NULL AND [t].ColumnA = '123'
   UNION ALL
   SELECT [t].ID, [srt].[depth] + 1 
   FROM dbo.Table t 
   INNER JOIN SelfReferencingTable srt ON [t].parentItemID = [srt].id
   WHERE [t].ColumnA = '123'       
)   
DELETE y FROM dbo.Table y
JOIN SelfReferencingTable x on x.ID = y.id
ORDER BY x.depth DESC

任何想法为什么这不起作用?

【问题讨论】:

    标签: sql sql-server-2008 sql-order-by sql-delete self-reference


    【解决方案1】:

    您无需按任何特定顺序删除它们。

    只需一次操作即可将它们全部删除。在语句末尾检查约束。

    假设您的递归 CTE 代码正确识别了您需要删除的所有行,您可以使用

    WITH SelfReferencingTable (ID)
    AS
    (
       SELECT id
       FROM dbo.Table
       WHERE parentItemID IS NULL AND [t].ColumnA = '123'
       UNION ALL
       SELECT [t].ID 
       FROM dbo.Table t 
       INNER JOIN SelfReferencingTable srt ON [t].parentItemID = [srt].id
       WHERE [t].ColumnA = '123'       
    )   
    DELETE 
    FROM dbo.Table 
    WHERE ID IN (SELECT id FROM SelfReferencingTable )
    

    【讨论】:

    • 谢谢!我试过这个,但我仍然遇到问题......原来是表数据完整性的问题。运行 DBCC CHECKCONSTRAINTS(Table) 后,它会发现一条不存在的 parentItemID 记录导致我出现问题。
    【解决方案2】:

    delete 子句不允许使用order bydelete 是单个原子操作,delete 操作的步骤按什么顺序完成都没有关系。

    一种常见的解决方案是在循环中删除没有依赖行的行:

    while 1=1
        begin
        delete  yt
        from    YourTable yt
        where   where ColumnA = '123'
                and not exists
                (
                select  *
                from    YourTable yt2
                where   yt2.parentItemId = yt.id
                )
    
        if @@rowcount = 0
            break
        end
    

    【讨论】:

    • 这不会只是删除没有孩子的父母吗?我需要删除 ColumnA = '123' 的所有记录,无论它们是父母还是孩子。
    • 这将删除所有没有子记录的记录。然后它循环遍历,并删除由于上一轮删除而不再有子记录的下一轮记录。这个过程一直持续到每条记录都被删除(除非记录具有自引用的父/子关系)。
    • 为 ColumnA 添加了条件。请注意,如果 ColumnA = '123' 的记录具有不同 ColumnA 的子项,则无法删除这些记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 2014-01-21
    相关资源
    最近更新 更多