以下方法首先估计新的最大值,然后使用递归 cte 查找所需节点“站点 1”的所有子节点,并在没有其他并发写入表的情况下确定它们可能的新 parent_id。
我建议在操作期间在transaction 和locking 表中运行以下命令,以防止并发表修改。
为了测试这种方法,我添加了一些额外的示例数据,我在下面包含了这些数据,但是您可能会在演示中看到该方法以及您的初始示例数据here
请参阅下面的工作 db fiddle 的输出:
架构 (MySQL v8.0)
CREATE TABLE node_structure_data (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(455) NOT NULL,
parent_id INT(10) UNSIGNED DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES node_structure_data (id)
ON DELETE CASCADE ON UPDATE CASCADE
);
INSERT INTO node_structure_data
(`id`, `title`, `parent_id`)
VALUES
('1', 'Division', NULL),
('2', 'Site 1', '1'),
('3', 'Paper', '2'),
('4', 'ms1', '3'),
('5', 'ms2', '3'),
('6', 'os1', '4'),
('7', 'os2', '4'),
('8', 'gs1', '1'),
('9', 'hs1', '3'),
('10','js1','9');
查询 #1
select 'Before Insert';
| Before Insert |
| Before Insert |
查询 #2
select * from node_structure_data;
| id |
title |
parent_id |
| 1 |
Division |
|
| 2 |
Site 1 |
1 |
| 3 |
Paper |
2 |
| 4 |
ms1 |
3 |
| 5 |
ms2 |
3 |
| 6 |
os1 |
4 |
| 7 |
os2 |
4 |
| 8 |
gs1 |
1 |
| 9 |
hs1 |
3 |
| 10 |
js1 |
9 |
查询 #3
select 'Possible Data Changes';
| Possible Data Changes |
| Possible Data Changes |
查询 #4
with recursive max_id AS (
SELECT MAX(id) as id FROM node_structure_data
),
child_nodes AS (
SELECT
n.id,
title,
parent_id,
m.id+1 as new_id,
parent_id as new_parent_id
FROM
node_structure_data n
CROSS JOIN
max_id as m
WHERE
title='Site 1'
UNION ALL
SELECT
n.id,
n.title,
n.parent_id,
@row_num:=IF(@row_num=0,c.new_id,0) + 1 + @row_num as new_id,
c.new_id
FROM
child_nodes c
INNER JOIN
node_structure_data n ON n.parent_id = c.id
CROSS JOIN (
SELECT @row_num:=0 as rn
) as vars
)
SELECT * FROM child_nodes;
| id |
title |
parent_id |
new_id |
new_parent_id |
| 2 |
Site 1 |
1 |
11 |
1 |
| 3 |
Paper |
2 |
12 |
11 |
| 4 |
ms1 |
3 |
13 |
12 |
| 5 |
ms2 |
3 |
14 |
12 |
| 9 |
hs1 |
3 |
15 |
12 |
| 6 |
os1 |
4 |
16 |
13 |
| 7 |
os2 |
4 |
17 |
13 |
| 10 |
js1 |
9 |
18 |
15 |
查询 #5 - 执行实际插入
INSERT INTO node_structure_data (title,parent_id)
with recursive max_id AS (
SELECT MAX(id) as id FROM node_structure_data
),
child_nodes AS (
SELECT
n.id,
title,
parent_id,
m.id+1 as new_id,
parent_id as new_parent_id
FROM
node_structure_data n
CROSS JOIN
max_id as m
WHERE
title='Site 1'
UNION ALL
SELECT
n.id,
n.title,
n.parent_id,
@row_num:=IF(@row_num=0,c.new_id,0) + 1 + @row_num as new_id,
c.new_id
FROM
child_nodes c
INNER JOIN
node_structure_data n ON n.parent_id = c.id
CROSS JOIN (
SELECT @row_num:=0 as rn
) as vars
)
SELECT title,new_parent_id FROM child_nodes ORDER BY new_id;
没有要显示的结果。
查询 #6
select 'AFTER INSERT';
| AFTER INSERT |
| AFTER INSERT |
查询 #7
select * from node_structure_data;
| id |
title |
parent_id |
| 1 |
Division |
|
| 2 |
Site 1 |
1 |
| 3 |
Paper |
2 |
| 4 |
ms1 |
3 |
| 5 |
ms2 |
3 |
| 6 |
os1 |
4 |
| 7 |
os2 |
4 |
| 8 |
gs1 |
1 |
| 9 |
hs1 |
3 |
| 10 |
js1 |
9 |
| 11 |
Site 1 |
1 |
| 12 |
Paper |
11 |
| 13 |
ms1 |
12 |
| 14 |
ms2 |
12 |
| 15 |
hs1 |
12 |
| 16 |
os1 |
13 |
| 17 |
os2 |
13 |
| 18 |
js1 |
15 |
View on DB Fiddle
让我知道这是否适合你。