sql - 删除表上引用自身的所有子项

标签 sql sql-server

假设我们有一个如下所示的表:

CREATE TABLE Test
(
    Id INT NOT NULL PRIMARY KEY IDENTITY(1,1),
    [Name] NVARCHAR(50) NOT NULL,
    ParentId INT NULL FOREIGN KEY REFERENCES Test(Id)
)

在此表中,我们有一个数据层次结构,可能类似于:

INSERT INTO Test (Name) 
VALUES ('ABC'), ('DEF'), ('HIJ');
GO

INSERT INTO TEST (Name, ParentId) 
VALUES ('KLM', 1), ('NOP', 1), ('QRS', 2), ('TUV', 2), ('XYX', 3)
GO

INSERT INTO Test (Name, ParentId) 
VALUES ('AAB', 4), ('AAC', 4), ('AAD', 4)

如何在不使用级联删除的情况下删除 id 1 及其所有子项?

最佳答案

您必须使用 rCTE(递归公共(public)表表达式)来递归遍历层次结构。然后你就可以JOIN该数据到您的表并删除相关行:

DECLARE @ID int = 1;

WITH rCTE AS(
    SELECT T.Id
    FROM dbo.Test T
    WHERE T.Id = @ID
    UNION ALL
    SELECT T.Id
    FROM rCTE r
         JOIN dbo.Test T ON r.Id = T.ParentId)
DELETE T
FROM dbo.Test T
     JOIN rCTe r ON T.Id = r.Id;

请注意,与您可能见过的一些示例不同,例如 CTE 用于 DELETE重复行,rCTE 不可更新(由于使用 UNION )。因此,您不能简单地执行 DELETE最后对 CTE 进行操作 ( DELETE FROM rCTE ),您必须将其用作 JOIN .

DB<>Fiddle

关于sql - 删除表上引用自身的所有子项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58042723/

相关文章:

python - 合并多个组 ID 以形成一个合并的组 ID?

sql-server - SQL Server如何在内部存储十进制类型值?

mysql - "read.sql"R 中的函数 : Using R as an SQL browser?

php - MySQL 查询 : Epoch Time Filter

sql-server - 如何在 Powershell 中循环 Datareader 并创建 DataTable

sql - 判断一个表是否有一些唯一的列

SQL-Server:将列定义为互斥

sql - 在 SQL Server 中创建触发器

sql - Bigquery - json_extract 从数组中提取所有元素

mysql - 如何查找数据库中值之间的关系