我有两张桌子:
\d folder
Table "public.folder"
Column | Type | Modifiers
---------+-----------------------+----------------------------------------------------
id | integer | not null default nextval('folder_id_seq'::regclass)
name | character varying(20) |
parent_id | integer |
Indexes:
"folder_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"fk_folder_1" FOREIGN KEY (parent_id) REFERENCES folder(id)
Referenced by:
TABLE "files" CONSTRAINT "fk_files_1" FOREIGN KEY (folder_id) REFERENCES folder(id)
TABLE "folder" CONSTRAINT "fk_folder_1" FOREIGN KEY (parent_id) REFERENCES folder(id)
\d files
Table "public.files"
Column | Type | Modifiers
----------+-----------------------+---------------------------------------------------
id | integer | not null default nextval('files_id_seq'::regclass)
name | character varying(20) |
folder_id | integer |
Indexes:
"files_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"fk_files_1" FOREIGN KEY (folder_id) REFERENCES folder(id)
select * from folder;
id | name | parent_id
----+---------+-----------
1 | home |
2 | folder2 | 1
3 | folder3 | 1
4 | folder4 | 2
5 | folder5 | 4
6 | folder6 | 5
(6 rows)
select * from files;
id | name | folder_id
----+-------+-----------
1 | file1 | 4
2 | file2 | 4
3 | file3 | 5
4 | file4 | 6
5 | file5 | 6
6 | file6 | 2
(6 rows)
现在我需要一个函数或游标或任何可以获得两个输入的文件,要复制的文件夹和要复制的目标文件夹,该函数应该将文件夹及其子文件夹复制到具有新id和父ID的同一个表中,如下所示,同时当文件夹被复制并插入文件表中的文件也要插入,plz帮我得到以下结果..
如果我正在将folder5复制到folder3,我的输出应该是这样的:
select * from folder;
id | name | parent_id
----+---------+-----------
1 | home |
2 | folder2 | 1
3 | folder3 | 1
4 | folder4 | 2
5 | folder5 | 4
6 | folder6 | 5
7 | folder5 | 3
8 | folder6 | 7
(8 rows)
当复制和插入文件夹时,和文件表也将被更新:
select * from files;
id | name | folder_id
----+-------+-----------
1 | file1 | 4
2 | file2 | 4
3 | file3 | 5
4 | file4 | 6
5 | file5 | 6
6 | file6 | 2
7 | file3 | 7
8 | file4 | 8
9 | file5 | 8
(9 rows)
答案 0 :(得分:0)
为什么不使用简单的更新?
BEGIN;
UPDATE folder
SET parent_id = 3
WHERE id = 5;
UPDATE files
SET folder_id = 3
WHERE folder_id = 5;
END;
答案 1 :(得分:0)
CREATE OR REPLACE FUNCTION tree_copy(INTEGER,INTEGER) RETURNS VOID AS $$
DECLARE
a ALIAS FOR $1; --ROOT FOLDER TO BE COPIED
b ALIAS FOR $2; --DESTINATION FOLDER
i INTEGER;
j INTEGER;
g INTEGER;
BEGIN
--DROP TABLE IF EXISTS temp1;
CREATE TEMPORARY TABLE temp1 AS(
WITH RECURSIVE CTE AS(
SELECT *, NEXTVAL('folder_id_seq') new_id FROM folder WHERE id = a
UNION ALL
SELECT folder.*,NEXTVAL('folder_id_seq') new_id FROM CTE
JOIN folder ON CTE.id = folder.parent_id)
SELECT C1.id, C1.new_id, C1.parent_id,
C2.new_id new_parent_id FROM CTE C1 LEFT JOIN
CTE C2 ON C1.parent_id = C2.id);
FOR i IN (WITH RECURSIVE t AS(SELECT id, parent_id FROM folder WHERE id = a
UNION SELECT f.id,f.parent_id FROM folder f, t AS t1 WHERE f.parent_id = t1.id)
SELECT id FROM t)
LOOP
SELECT new_parent_id INTO g FROM temp1 WHERE id = i;
INSERT INTO folder(id,name,parent_id)VALUES(
(SELECT new_id FROM temp1 WHERE id = i),
(SELECT name FROM folder WHERE id = i),COALESCE(g,b));
FOR j IN (SELECT id FROM files WHERE folder_id = i)
LOOP
INSERT INTO files(id,name,folder_id) VALUES (
NEXTVAL('files_id_seq'),(SELECT name FROM files WHERE id = j),
(SELECT new_id FROM temp1 WHERE id = i));
END LOOP;
END LOOP;
DROP TABLE temp1;
END;
$$ LANGUAGE PLPGSQL;
这会像我想的那样......