Postgresql копирует данные в таблицу дерева
у меня есть таблица с древовидной структурой, столбцы id
, category
, parent_id
теперь мне нужно скопировать узел и его дочерний узел на другой узел, при копировании категория должна быть такой же, но с новым id и parent_id..
мой вход будет node to copy
& destination node to copy
Я объяснил древовидную структуру в файле изображения..
мне нужна функция для этого..,
версия PostgreSQL 9.1.2
Column | Type | Modifiers
-----------+---------+-------------------------------------------------
id | integer | not null default nextval('t1_id_seq'::regclass)
category | text |
parent_id | integer |
Indexes:
"t1_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"fk_t1_1" FOREIGN KEY (parent_id) REFERENCES t1(id)
Referenced by:
TABLE "t1" CONSTRAINT "fk_t1_1" FOREIGN KEY (parent_id) REFERENCES t1(id)
1 ответов
(протестировано под PostgreSQL 8.4.3)
следующий запрос назначает новые идентификаторы под-дереву под узлом 4 (см. nextval
), а затем находит соответствующие новые коды родителей (см. LEFT JOIN
).
WITH RECURSIVE CTE AS (
SELECT *, nextval('t1_id_seq') new_id FROM t1 WHERE id = 4
UNION ALL
SELECT t1.*, nextval('t1_id_seq') new_id FROM CTE JOIN t1 ON CTE.id = t1.parent_id
)
SELECT C1.new_id, C1.category, C2.new_id new_parent_id
FROM CTE C1 LEFT JOIN CTE C2 ON C1.parent_id = C2.id
результат (по вашим тестовым данным):
new_id category new_parent_id
------ -------- -------------
9 C4
10 C5 9
11 C6 9
12 C7 10
как только у вас это есть, его легко вставить обратно в таблицу, вам просто нужно быть осторожным, чтобы повторно подключить корень под-дерева с соответствующим родителем (8 в этом кейс, смотри COALESCE(new_parent_id, 8)
):
INSERT INTO t1
SELECT new_id, category, COALESCE(new_parent_id, 8) FROM (
WITH RECURSIVE CTE AS (
SELECT *, nextval('t1_id_seq') new_id FROM t1 WHERE id = 4
UNION ALL
SELECT t1.*, nextval('t1_id_seq') new_id FROM CTE JOIN t1 ON CTE.id = t1.parent_id
)
SELECT C1.new_id, C1.category, C2.new_id new_parent_id
FROM CTE C1 LEFT JOIN CTE C2 ON C1.parent_id = C2.id
) Q1
после этого таблица содержит следующие данные:
new_id category new_parent_id
------ -------- -------------
1 C1
2 C2 1
3 C3 1
4 C4 2
5 C5 4
6 C6 4
7 C7 5
8 C8 3
9 C4 8
10 C5 9
11 C6 9
12 C7 10