I have table with tree structure, columns are id
, category
, parent_id
Now I need a copy a node and its child's to a another node, while copying, the category must be same, but with new id and parent_id..
My input will be node to copy
& destination node to copy
I have explained the tree structure in the image file..
i need a function to do so..,
PostgreSQL version 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)
Click the tab for the table with the columns you want to copy and select those columns. From the Edit menu, click Copy. Click the tab for the table into which you want to copy the columns. Select the column you want to follow the inserted columns and, from the Edit menu, click Paste.
COPY moves data between PostgreSQL tables and standard file-system files. COPY TO copies the contents of a table to a file, while COPY FROM copies data from a file to a table (appending the data to whatever is in the table already). COPY TO can also copy the results of a SELECT query.
If you COPY TO a file already containing data, the existing data will be overwritten.
(tested under PostgreSQL 8.4.3)
The following query assigns new IDs to the sub-tree under node 4 (see the nextval
) and then finds the corresponding new IDs of parents (see the 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
Result (on your test data):
new_id category new_parent_id
------ -------- -------------
9 C4
10 C5 9
11 C6 9
12 C7 10
Once you have that, it's easy to insert it back to the table, you just have to be careful to reconnect the sub-tree root with the appropriate parent (8 in this case, see the 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
After that, the table contains the following data:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With