使用 SQL 更新层次结构中的父记录
Posted
技术标签:
【中文标题】使用 SQL 更新层次结构中的父记录【英文标题】:Use SQL to update parent records in hierarchy 【发布时间】:2020-09-28 13:25:23 【问题描述】:我有一个具有父子层次结构的表。我正在尝试编写一个更新语句,该语句将在给定设备 ID 列表的情况下更新该 ID 的记录及其所有父记录。
CREATE TABLE [Equipment]
(
[id] [int] NOT NULL,
[Parentid] [int] NULL,
[ActiveInExecution] [bit] NULL,
)
所以我的想法是,如果我有一个 ID 列表,比如说 3、5、6,我应该能够将它们的所有活动位更新为 true(是的,我意识到在这种情况下 id 5 将是多余的)
我开始为此做一个光标,但我觉得这太过分了。
任何帮助将不胜感激。
谢谢。
id | parentid | active
---+----------+--------
1 | null | 0
2 | 1 | 0
3 | 2 | 0
4 | null | 0
5 | 4 | 0
6 | 5 | 0
【问题讨论】:
【参考方案1】:您可以使用递归公用表表达式,然后在您的UPDATE
语句的WHERE
中使用EXISTS
,以查看是否在层次结构中找到id
:
CREATE TABLE dbo.[Equipment]
(
[id] [int] NOT NULL,
[Parentid] [int] NULL,
[ActiveInExecution] [bit] NULL,
);
GO
INSERT INTO dbo.Equipment (id,
Parentid,
ActiveInExecution)
VALUES (1,NULL,0),
(2, 1 ,0),
(3, 2 ,0),
(4,NULL,0),
(5, 4 ,0),
(6, 5 ,0);
GO
WITH rCTE AS(
SELECT E.id,
E.Parentid,
E.ActiveInExecution
FROM dbo.Equipment E
WHERE E.id IN (3,5,6)
UNION ALL
SELECT E.id,
E.Parentid,
E.ActiveInExecution
FROM dbo.Equipment E
JOIN rCTE r ON E.Parentid = r.id)
UPDATE E
SET ActiveInExecution = 1
FROM dbo.Equipment E
WHERE EXISTS(SELECT 1
FROM rCTE r
WHERE r.id = E.id);
GO
SELECT *
FROM dbo.Equipment;
【讨论】:
【参考方案2】:一个选项使用递归查询来构建层次结构树,然后使用连接来更新相关行。假设您要更新 id 3
及其所有父母:
with cte as (
select * from equipment where id = 3
union all
select e.*
from equipment e
inner join cte c on c.parentid = e.id
)
update e
set e.activeInExecution = 1
from equipment e
inner join cte c on c.id = e.id
【讨论】:
以上是关于使用 SQL 更新层次结构中的父记录的主要内容,如果未能解决你的问题,请参考以下文章
由于多列上的唯一索引,无法更新 Rails 中的父记录和嵌套记录
从 spark 数据框或 sql 中选择具有偏好层次结构的多个记录